Skip to content

Instantly share code, notes, and snippets.

@laser
Last active December 31, 2015 11:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laser/7983206 to your computer and use it in GitHub Desktop.
Save laser/7983206 to your computer and use it in GitHub Desktop.
Modifying sync (and consumer) to handle concurrent stuff

Some notes about the gist:

  • Calling "sync" creates an array to keep track of return values from any asynchronous operation.

  • The "resume" method is called in your generator code and its return value is passed as the callback to your asynchronous operation. Calling "resume" causes a counter to increment, letting your "sync" method know how many asynchronous operations are in flight.

  • The return value of "resume" is a function that causes the result of the asynchronous operation to be placed into the data structure in #1. Immediately after doing this assignment, we check to see if there are any outstanding asynchronous operations. If not, we resume the generator with either an (ordered) array containing the results of our asynchronous operations or (in the event of only one operation having been fired off)

The important thing to note is that both asynchronous operations have been fired off before yielding. Each callback (passed to these asynchronous calls) is the return value from the call to "resume" - which caused our counter to increment. Both calls to "resume" happen on the same tick of the event loop, before the generator suspends.

function _get(url, callback) {
var x = new XMLHttpRequest();
x.onreadystatechange = function() {
if (x.readyState == 4) {
callback(null, x.responseText);
}
};
x.open("GET", url);
x.send();
}
function sync(gen) {
var iterable, resume, check, vals, ops;
vals = [];
ops = 0;
check = function() {
if (vals.length == ops) {
iterable.next(ops == 1 ? vals[0] : vals);
}
}
resume = function(err, retVal) {
var slot = ops;
ops++;
return function(err, retVal) {
if (err) iterable.raise(err);
vals[slot] = retVal;
check();
};
};
iterable = gen(resume);
iterable.next();
}
sync(function* (resume) {
var responses = yield [_get("index.html", resume()), _get("shared.css", resume())];
log(responses);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment