None of the answers provided thus far actually execute in the one at a time way you're looking for.
Promises invoke their executor function upon construction. So, by nature, in order to use Promise.all, all of your async operations must already be running. Think of it as Promise.allAtOnce.
@Daniel's answer comes close, but Array#forEach executes synchronously, so it still runs all at once:
const wait = (time, message) => new Promise(resolve => {
setTimeout(_=>{
console.log(message);
resolve();
}, time);
});
let promises = [];
[3000, 2000, 1000].forEach(
(time, index) => promises.push(wait(time, ++index))
)
Promise.all(promises);
/*
Even though `3000` was the first item,
`1000` resolves first because all the `Promise`
executors run at once.
Output:
3
2
1
*/
The most succinct way to execute one at a time is with an async loop:
const wait = (time, message) => new Promise(resolve => {
setTimeout(_=>{
console.log(message);
resolve();
}, time);
});
const iterate = async _ => {
let index = 0;
for (let time of [3000, 2000, 1000]) try {
await wait(time, ++index)
} catch (e) {
console.error(e);
}
}
iterate();
/*
Even though `3000` takes 3X longer to resolve,
the `wait` of `3000` resolves first,
because it is first in the iteration.
Output:
1
2
3
*/
If you want to avoid using async/await, just chain the promises with a loop. This will produce the same result:
const wait = (time, message) => new Promise(resolve => {
setTimeout(_=>{
console.log(message);
resolve();
}, time);
});
const iterate = _ => {
// initiate with an already-resolved promise
let lastPromise = Promise.resolve();
let index = 0;
for (let time of [3000, 2000, 1000]) {
// chain each promise to the promise returned by the previous item.
lastPromise = lastPromise
.then(result => wait(time, ++index))
.catch(console.error);
}
return lastPromise;
}
iterate();
/*
Even though `3000` takes 3X longer to resolve,
the `wait` of `3000` resolves first,
because it is first in the iteration.
Output:
1
2
3
*/