简体   繁体   中英

Is there a way to guarantee `Promise.all` resolves after the `then` chain of an inner promise?

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

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') }) 

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();
})

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') }) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM