I'm playing around with a recursive generator function that returns values asynchronously. I'm using a coroutine wrapper function to call it. Code and JSBin below:
http://jsbin.com/nuyovay/edit?js,console
let log = console.log.bind(console);
let err = console.error.bind(console);
function coroutine(generatorFn){
return function co() {
let generator = generatorFn.apply(this, arguments);
function handle(result) {
console.log(result);
if (result.done) {
return Promise.resolve(result.value);
}
return Promise.resolve(result.value)
.then(
res => handle(generator.next(res)),
err => handle(generator.throw(err))
);
}
try {
return handle(generator.next());
} catch (err) {
return Promise.reject(err);
}
};
}
function sleep(dur) {
return new Promise(res => {
setTimeout(() => { res() }, dur);
});
}
function* recurse(limit = 5, count = 0) {
if(count < limit) {
yield sleep(100).then(() => Promise.resolve(++count));
yield* recurse(limit, count);
}
else {
return count;
}
}
let test = coroutine(recurse);
test().then(log).catch(err);
Running this returns:
Object {value: Promise, done: false}
Object {value: Promise, done: false}
Object {value: Promise, done: false}
Object {value: Promise, done: false}
Object {value: Promise, done: false}
// `value` should be 5
Object {value: undefined, done: true}
How come the final return from the generator is undefined? When I adapt the above for use with bluebird's Promise.coroutine, I get the same result. Am I missing something fundamental about recursive generators? How do I get it to { value: 5, done: true }?