Executing Promises In A Sequence
Solution 1:
Firstly, promises may or may not start executing immediately after creation. (Note: by immediately, it is relative to the execution loop.)
In your above code, p1
to p5
starts counting down as soon as you leave the current execution loop.
To ensure the promises does not get executed before you want them to, you would have to wrap them in a promise generating function.
var p1 = function(){
returnnewPromise(function(resolve, reject){
console.log('p1');
setTimeout(resolve, 5000, "one");
});
};
var p2 = function(){
returnnewPromise(function(resolve, reject){
console.log('p2');
setTimeout(resolve, 3000, "two");
});
};
var p3 = function(){
returnnewPromise(function(resolve, reject){
console.log('p3');
setTimeout(resolve, 2000, "three");
});
};
var p4 = function(){
returnnewPromise(function(resolve, reject){
console.log('p4');
setTimeout(resolve, 1000, "four");
});
};
var p5 = function(){
returnnewPromise(function(resolve, reject){
console.log('p5');
setTimeout(resolve, 4000, "five");
});
};
For the above case, if you already know the number of promises you have, you can simply chain the promises together:
p1().then(p2).then(p3).then(p4).then(p5).then(function(){
// Hurray! All done!
console.log("All done :)");
});
However, if you have a variable amount of promises to chain in sequence, you would have to make use of loops (see @PitaJ's answer) or Array.reduce
.
var arrayOfPromiseGeneratingFunctions = [p1, p2, p3, p4, p5]; // Can be of any size.// Take the first promise-generating function as chain initializervar initialFn = arrayOfPromiseGeneratingFunctions.shift();
// Here we're effectively doing promise chaining like the simple solution abovevar finalPromise = arrayOfPromiseGeneratingFunctions.reduce(function(previousPromise, fn){
return previousPromise.then(fn)
}, initialFn());
finalPromise.then(function(){
// Last promise called
});
This solution is suitable for an arbitrary number of sequentially executed promises, so as long as you wrap the promises with a function.
Some other catches about this implementation: 1. In the example we wrap p1 to p5 into a function, so that they don't get executed in any way before you want it to. 2. You can pass results promise results from one to another, by adding the parameter in the promise-generating function. Since the first parameter would effectively be the resolve result of the last promise.
Further reading: https://github.com/kriskowal/q#sequences
Solution 2:
Promise
is executed immediately on creation. You have to use then
to chain actions.
newPromise(function(resolve, reject){
console.log('p1');
setTimeout(resolve, 5000, "one");
}).then(() => {
console.log('p2');
setTimeout(resolve, 3000, "two");
}).then(() => {
console.log('p3');
setTimeout(resolve, 2000, "three");
}).then(() => {
console.log('p4');
setTimeout(resolve, 1000, "four");
}).then(() => {
console.log('p5');
setTimeout(resolve, 4000, "five");
});
Solution 3:
You can do something like this:
functionsequential(promiseArr) {
var p = Promise.resolve(), i = 0, l = promiseArr.length;
for (; i < l; i += 1) {
p = p.then(promiseArr[i]);
}
return p;
}
Edit: Fixed it. Would have failed because p
wasn't initialized to start.
Solution 4:
Let me rephrase your problem.
You have a function which return a promise. You need to call this function again and again with different arguments only when the previous promise is resolved.
Lets imagine following is the function.
functiongetPromise(arg) {
returnnewPromise(function(resolve){
setTimeout(resolve, Math.random() * 10000, [arg]);
})
};
Here is your argument list
var promiseSetup = ['apple', 'orange', 'grapes'];
You can have objects which contain functions to be executed too instead of simple demo params here.
Now I'm going to put down the logic which will execute above promise functions repeatedly with each of the arguments. This will be done in a sequence.
function promiseWaterfall(args, promFunc, idx) {
if (idx >= args.length)
return;
console.log('executing ' + args[idx]);
promFunc(args[idx]).then(function(){
promiseWaterfall(args, promFunc, idx + 1)
});
}
Explanation
The above function is recursive. It will call itself with an advanced index value only when the previous promise it obtained is resolved.
Also note that you can execute a function every time a promise is resolved. You can make the "apple" an apple object like this
[{arg: "apple", func: executeApple}]
Then execute this function where we log the console message.
Post a Comment for "Executing Promises In A Sequence"