I have a loop which calls a method that does stuff asynchronously. This loop can call the method many times. After this loop, I have another loop that needs to be executed only when all the asynchronous stuff is done.
So this illustrates what I want:
for (i = 0; i < 5; i++) {
doSomeAsyncStuff();
}
for (i = 0; i < 5; i++) {
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
I'm not very familiar with promises, so could anyone help me to achieve this?
This is how my doSomeAsyncStuff()
behaves:
function doSomeAsyncStuff() {
var editor = generateCKEditor();
editor.on('instanceReady', function(evt) {
doSomeStuff();
// There should be the resolve() of the promises I think.
})
}
Maybe I have to do something like this:
function doSomeAsyncStuff() {
var editor = generateCKEditor();
return new Promise(function(resolve,refuse) {
editor.on('instanceReady', function(evt) {
doSomeStuff();
resolve(true);
});
});
}
But I'm not sure of the syntax.
You can use Promise.all
(spec, MDN) for that: It accepts a bunch of individual promises and gives you back a single promise that is fulfilled when all of the ones you gave it are fulfilled, or rejected when any of them is rejected. The results in the fulfillment array are in the same order as the promises in the input array.
So if you make doSomeAsyncStuff
return a promise, then:
const promises = [];
// ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− use `const` or `let`, not `var`
for (let i = 0; i < 5; i++) {
// ^^^−−−−−−−−−−−−−−−−−−−−−−−− added missing declaration
promises.push(doSomeAsyncStuff());
}
Promise.all(promises)
.then(() => {
for (let i = 0; i < 5; i++) {
// ^^^−−−−−−−−−−−−−−−− added missing declaration
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
})
.catch((e) => {
// handle errors here
});
MDN has an article on promises here. I also cover promsies in detail in Chapter 8 of my book JavaScript: The New Toys, links in my profile if you're interested.
Here's an example:
function doSomethingAsync(value) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Resolving " + value);
resolve(value);
}, Math.floor(Math.random() * 1000));
});
}
function test() {
const promises = [];
for (let i = 0; i < 5; ++i) {
promises.push(doSomethingAsync(i));
}
Promise.all(promises)
.then((results) => {
console.log("All done", results);
})
.catch((e) => {
// Handle errors here
});
}
test();
Sample output (because of the Math.random
, what finishes first may vary, but the "All done" line will be at the end):
Resolving 3 Resolving 2 Resolving 1 Resolving 4 Resolving 0 All done [0,1,2,3,4]
Note, again, that the contents of the fulfillment array are in the order of the promises in the input array (not the order the promises were fulfilled in).