Last active
March 30, 2017 09:36
-
-
Save drodsou/75bd6d9ab37079b26588a5792ef9f5e1 to your computer and use it in GitHub Desktop.
Generator deasync pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* returns a function that runs an async generator (one which yields async functions), usings auto yield/next thanks to an 'args.next' | |
* The created function expects as parameter an optional object with a {cb:callbackFn} property plus aditional custom arguments | |
* Can also make a onliner gen runner with it: function runAsyncGen(gen, args) { newAsyncFn(gen)(args) } | |
*/ | |
function createAsyncFn (gen) { | |
return function(args={}, cb) { | |
//var cb = (typeof args === 'function') ? args : args.cb | |
it = gen(args) // create iterator from generator, and pass a common object to communicate | |
args.next = (res)=>{ // pre made callback to pass to async funcions inside generator to keep going on | |
let ret = it.next(res) | |
if (ret.done && typeof cb === 'function') cb(ret.value) // "return" statement is another "yield" with .done = true | |
} | |
args.nextIfOK = (err,res)=>{ // to quickly handle (err, res) standard nodejs returns inside a try/catch | |
if (!err) args.next(res) | |
else it.throw(new Error(err)) | |
} | |
it.next() // start iterator | |
} | |
} | |
// -------------------------------- EXAMPLE | |
// Nodejs async readline in a sync fashion | |
// the 'args' parameter here is the args parameter passed to the funcion, plus a .next function of the current iterator | |
var promptUser = createAsyncFn( function* (args) { | |
var r = require('readline') | |
var rl = r.createInterface({input: process.stdin, output: process.stdout }) | |
// magic here | |
var answerA = yield rl.question(`Hello ${args.name}, do you want this? `, args.next) // or somting like (err, res)=>args.next({err,res}) | |
console.log("mmm, let me think about it...") | |
yield setTimeout(args.next, 1000) | |
var answerB = yield rl.question('are you sure? ', args.next) | |
rl.close() // readline boilerplate | |
return {answerA, answerB} // the last 'yield' | |
}) | |
// now make use of it | |
promptUser({ name:'Neo', cb:(r)=>{ | |
console.log('\nAnswers:',r) | |
}}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment