Skip to content

Instantly share code, notes, and snippets.

@cbrunnkvist
Last active January 27, 2017 10:12
Show Gist options
  • Save cbrunnkvist/0f4cc3655bdcca2a0e1ea0062be45ecc to your computer and use it in GitHub Desktop.
Save cbrunnkvist/0f4cc3655bdcca2a0e1ea0062be45ecc to your computer and use it in GitHub Desktop.
Extensively commented version of the simplest possible ES6 `co`/`Bluebird.coroutine`-like implementation
function executeWithCoroutine(generatorFunction) {
function letItYield(rejectionError, resolvedValue) {
// 1st round: resolvedValue is empty at kick off (see last line in executeAsCoroutine)
// 2nd round and onwards: resolvedValue is the value we pass ourselves at promise resolution
// let the generatorObject deal with the error in case of promise rejection
if (rejectionError) {
generatorObject.throw(rejectionError)
}
// what we pass into next() will be what the current yield expression returns
// as execution resumes inside the generatorFunction
// NOTE: discarded on the 1st call to .next(), which instead just starts generatorFunction()
const iteratorResult = generatorObject.next(resolvedValue)
// stop recursion when the generatorFunction returned/is done
if (iteratorResult.done) {
return iteratorResult.value
}
// the magic: assuming that we pass Promises to yield,
// let their eventual fulfillment trigger iteration
return iteratorResult.value.then(value => letItYield(null, value), error => letItYield(error))
}
const generatorObject = generatorFunction()
// kick things off and return the outermost promise, allowing .then(console.log) at the end just for fun
return letItYield()
}
executeWithCoroutine(function* () {
const resultOfAsyncOp1 = yield Promise.resolve('everything')
const resultOfAsyncOp2 = yield Promise.resolve('is fine')
const finalSyncResult = `${resultOfAsyncOp1} ${resultOfAsyncOp2}`.toUpperCase()
return finalSyncResult
}).then(console.log)
// -> EVERYTHING IS FINE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment