Skip to content

Instantly share code, notes, and snippets.

@dtothefp
Created December 6, 2015 03:04
Show Gist options
  • Save dtothefp/13843cfb7e257c246e1f to your computer and use it in GitHub Desktop.
Save dtothefp/13843cfb7e257c246e1f to your computer and use it in GitHub Desktop.
/**
* Go one step further and create a `run` function that takes a `generator` function
* as it's only argument
* https://strongloop.com/strongblog/how-to-generators-node-js-yield-use-cases/
*
* a) `run` caches the generator object
* b) contains a private `_next` function that initially starts the generator
* c) `_next` also acts as the callback to the Node callback signature (i.e. (err, data) => {})
* - first time around it obtains the "thunkified" function from `yield`
* - `_next` is then called recursively by the "thunked" function
* - `_next` also advances the generator so the data from the cb is returned from `yield`
* - the whole process happens over and over if there are multiple yields
*/
function run(genFn) {
const it = genFn();
function _next(err, val) {
if (err) it.throw(err); //throw err to be caught in generator
//get the generator object
//a) the first time through val === undefined as yield returns what is returned from the thunk
//b) next time through `val` will be the value passed as the second arg to the
// node callback signature
// - essentially this will "dependency inject" the async value from the `yield`
const cont = it.next(val);
if (cont.done) return;
const cb = cont.value; //yielded function from thunk that takes a callback as only arg
//call the callback which exposes data inside the generator
//the "confusing" part is that `_next` is the cb passed as the second arg to `fs.readFile` or whatever is "thunked"
//so it will only be called again when the async action calls it's cb
//therefore, the generator is paused at the yield, until `_next` is called by `fs.readFile` or whatever
//and therefore the generator object `.next` method is called advancing the
//generator so on and so forth until the generator is done `{value: ..., done: true}`
cb(_next);
}
_next(); //start the generator
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment