Reputation: 11153
Is there a way to guarantee Promise.all
resolves after the then
chain of an inner promise?
Example:
const promiseOne = new Promise((resolve, reject) => {
setTimeout(function(){
console.log('promiseOne after 1 second')
resolve()
}, 1000)
}).then(()=> {
setTimeout(function(){
console.log('promiseOne then chain, after 2 seconds')
}, 1000)
})
Promise.all([promiseOne])
.then(() => {
console.log('Promise.all then chain after 1 second')
})
Logs:
promiseOne after 1 second
Promise.all then chain after 1 second
promiseOne then chain, after 2 seconds
Upvotes: 2
Views: 76
Reputation: 5671
The easiest way is to pass the promise returned by the last then
, which you are already doing. If you take your console log in the first then
out of the setTimeout
you'll see that it is executing in the order you want.
The reason it's logging in that order is because setTimeout
is asynchronous.
Try like so:
const promiseOne = new Promise((resolve, reject) => {
setTimeout(function(){
console.log('promiseOne after 1 second')
resolve()
}, 1000)
}).then(()=> new Promise(resolve => {
setTimeout(function(){
console.log('promiseOne then chain, after 2 seconds')
resolve()
}, 1000)
})
By having the first then
return a promise, it will wait till after your setTimeout
and continue in the correct order.
EDIT: As a bonus, when using setTimeout
s, this helper is super useful:
const wait = ms => () => new Promise(resolve => setTimeout(resolve,ms));
Which you can use like so:
Promise.resolve()
.then(wait(2000))
.then(() => {
doSomething();
})
Upvotes: 1
Reputation: 13356
You have to return a new promise in the then chain of the inner promise:
const promiseOne = new Promise((resolve, reject) => {
setTimeout(function(){
console.log('promiseOne after 1 second')
resolve();
}, 1000)
}).then(()=> {
return new Promise((resolve, reject) => {
setTimeout(function(){
console.log('promiseOne then chain, after 2 seconds');
resolve();
}, 1000)
});
})
Promise.all([promiseOne])
.then(() => {
console.log('Promise.all then chain after 1 second')
})
Upvotes: 1
Reputation: 32212
The then
s are running in the correct order, but the first one is simply setting a timeout, so the console.log
s run in the opposite order to the then
s. If you want to wait for that timeout to run before continuing the chain, you need to use an additional promise returned from that then
:
const promiseOne = new Promise((resolve, reject) => {
setTimeout(function(){
console.log('promiseOne after 1 second')
resolve()
}, 1000)
}).then(() => new Promise((resolve, reject) => {
setTimeout(function(){
console.log('promiseOne then chain, after 2 seconds')
resolve()
}, 1000)
})
)
Promise.all([promiseOne])
.then(() => {
console.log('Promise.all then chain after 1 second')
})
Upvotes: 1