Reputation: 980
Pretty new to es6 and curious to know whether now with Promises, I can do away with future.wait()
I have a method called execute()
, which starts a chain of promises. I have two requirements of this method:
execute()
should only return when the whole chain of promises has completed executing (i.e. I want to block until the last promise is complete)Here is my sample code:
/* Require dependencies */
require('babel/polyfill');
class PromiseWaiter {
/* Constructor */
constructor() {
}
/* Methods */
execute() {
let _this = this;
runPromiseGenerator(function *promiseGenerator() {
yield _this.asyncMethod1();
yield _this.asyncMethod2();
yield _this.asyncMethod3();
});
return true;
}
asyncMethod1() {
return returnDummyPromise('method 1', 800);
}
asyncMethod2() {
return returnDummyPromise('method 2', 200);
}
asyncMethod3() {
return returnDummyPromise('method 3', 200);
}
}
var runPromiseGenerator = function(generator) {
var it = generator(), ret;
// asynchronously iterate over generator
(function iterate(val) {
ret = it.next(val);
if (!ret.done) {
// poor man's "is it a promise?" test
if ("then" in ret.value) {
// wait on the promise
ret.value.then(iterate);
}
// immediate value: just send right back in
else {
// avoid synchronous recursion
setTimeout( function(){
iterate(ret.value);
}, 0);
}
}
})();
};
var returnDummyPromise = function(methodName, timeout) {
console.log('starting %s', methodName);
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('finished %s', methodName);
resolve();
}, timeout);
})
};
module.exports = PromiseWaiter;
Here is what I run on the node console to test & the current output:
> p = new PromiseWaiter()
{}
> p.execute()
starting method 1
true
> finished method 1
starting method 2
finished method 2
starting method 3
finished method 3
What I want to see is:
> p = new PromiseWaiter()
{}
> p.execute()
starting method 1
finished method 1
starting method 2
finished method 2
starting method 3
finished method 3
true
>
In the past I would have done this using
fut = new Future();
// set off chain passing future
future.wait();
Wanted to pick the brains of the best and brightest out there.
Thanks in advance for your time! Elliott
Upvotes: 1
Views: 164
Reputation: 161457
You'll need to return a promise that will resolve when the generator has completed. I'd really recommend using an existing implementation like co
however if you wanted to expand your own implementation:
var runPromiseGenerator = function(generator) {
return new Promise(function(resolve, reject){
var it = generator(), ret;
// asynchronously iterate over generator
(function iterate(val) {
try {
ret = it.next(val);
if (!ret.done) {
Promise.resolve(ret.value).then(iterate, reject);
}
else {
resolve(ret.value);
}
}
catch (e){
reject(e);
}
})();
});
};
then you can alter your execute
to be
execute() {
let _this = this;
return runPromiseGenerator(function *promiseGenerator() {
yield _this.asyncMethod1();
yield _this.asyncMethod2();
yield _this.asyncMethod3();
});
}
and do
p.execute().then(function(){
// done
});
Alternatively, you can use your existing function to then call it, e.g.
runPromiseGenerator(function *promiseGenerator() {
yield p.execute();
// do something after execution
});
Upvotes: 1