Skip to content

Instantly share code, notes, and snippets.

@elrac
Last active August 29, 2015 14:26
Show Gist options
  • Save elrac/9ee91a3ce4c7b128e225 to your computer and use it in GitHub Desktop.
Save elrac/9ee91a3ce4c7b128e225 to your computer and use it in GitHub Desktop.
Async using generators.
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;
}
// 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
// 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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment