This is an example of using promises and generator funcitons to implement async/await. The general structure and base code was from examples I found on the web. My addition is the wrapper so the async functions can be called as functions that return a promise, and the complete error handling. Errors should be handleable like in the spec for async/await. That means that you can put try/catch around a yeild and it will catch thrown errors, but if you fail to catch an error it will bubble up to the top level promise and be caught by the .catch() there.
Last active
August 29, 2015 14:26
-
-
Save elrac/9ee91a3ce4c7b128e225 to your computer and use it in GitHub Desktop.
Async using generators.
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
function async(f) { | |
var func = f; | |
return function () { | |
return async_(func, arguments); | |
} | |
} | |
function async_(g, args) { | |
var it = g.apply(this, args); | |
var ret; | |
var prom = new Promise(function (resolve, reject) { | |
// asynchronously iterate over generator | |
function next(val) { | |
try { | |
iterate(it.next(val)); | |
} catch (e) { | |
console.log('caught error a', e); | |
reject(e); | |
} | |
} | |
function error(err) { | |
try { | |
iterate(it. | |
throw (err)); | |
} catch (err2) { | |
console.log('caught error b', err2); | |
reject(err2); | |
} | |
} | |
function iterate(ret) { | |
if (!ret.done) { | |
// poor man's "is it a promise?" test | |
if ("then" in ret.value) { | |
// wait on the promise | |
ret.value.then(next) | |
. | |
catch (function (err) { | |
error(err); | |
}); | |
} | |
// immediate value: just send right back in | |
else { | |
// avoid synchronous recursion | |
setTimeout(function () { | |
next(ret.value); | |
}, 0); | |
} | |
} else { | |
resolve(ret.value); | |
} | |
}; | |
next(); | |
}); | |
return prom; | |
} |
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
// http://jsfiddle.net/naxhguqk/ | |
var waitFunc = function(toReturn,waitTime){ | |
var prom = new Promise(function(resolve){ | |
setTimeout(function(){ | |
resolve(toReturn); | |
}, waitTime); | |
}); | |
return prom; | |
} | |
var main = async(function*(input){ | |
console.log('message a:',input); | |
var res = yield waitFunc('message b',1000); | |
console.log(res); | |
res = yield innerFunc(); | |
console.log(res); | |
return 'end'; | |
}) | |
var innerFunc = async(function*(){ | |
console.log('message c:inner func'); | |
var res = yield waitFunc('message d: message inner func',1000); | |
console.log(res); | |
return 'message e:end inner func'; | |
}); | |
main('main was called with this') | |
.then(function(res){ | |
console.log('message f:end value:',res); | |
}); | |
//message a: main was called with this | |
//<one second pause> | |
//message b | |
//message c:inner func | |
//<one second pause> | |
//message d: message inner func | |
//message e:end inner func | |
//message f:end value: end |
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
// http://jsfiddle.net/4btk5z12/ | |
var outerWithTry = async(function*(){ | |
try{ | |
var res = yield passthrough(); | |
console.log('outerWithTry got a return', res); | |
}catch(e){ | |
console.log('outerWithTry caught an error',e); | |
throw e + ' rethrown'; | |
} | |
return 'a value'; | |
}); | |
var passthrough = async(function* (func2){ | |
yield functionWithError(); | |
}); | |
var functionWithError = async(function*(){ | |
console.log('throwing an error'); | |
throw 'an error'; | |
}); | |
outerWithTry().catch(function(err){ | |
console.log('outer error',err); | |
}); | |
//throwing an error | |
//outerWithTry caught an error an error | |
//outer error an error rethrown |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment