【问题标题】:Is there a way to guarantee `Promise.all` resolves after the `then` chain of an inner promise?有没有办法保证 `Promise.all` 在内部承诺的 `then` 链之后解析?
【发布时间】:2018-04-16 01:23:44
【问题描述】:

有没有办法保证Promise.all 在内部承诺的then 链之后解析?

例子:

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

日志:

promiseOne after 1 second
Promise.all then chain after 1 second
promiseOne then chain, after 2 seconds

【问题讨论】:

  • 在“promiseOne then chain, after 2 seconds”回调中返回另一个在 1 秒后解决的承诺。现在你的回调返回未定义。并立即解决。
  • promise.all 就是这样工作的,无论如何将它用于单个 Promise 是多余的
  • 你的答案在这里Using setTimeout in a promise chain

标签: javascript promise


【解决方案1】:

thens 以正确的顺序运行,但第一个只是设置超时,因此console.logs 的运行顺序与thens 的顺序相反。如果您想在继续执行链之前等待该超时运行,您需要使用从该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')
})

【讨论】:

  • 叹息不敢相信我没有注意到
【解决方案2】:

你必须在内部promise的then链中返回一个新的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')
})

【讨论】:

    【解决方案3】:

    最简单的方法是传递你已经在做的最后一个then 返回的承诺。如果您将控制台日志从setTimeout 中的第一个then 登录,您会看到它正在按照您想要的顺序执行。

    之所以按此顺序登录,是因为 setTimeout 是异步的。

    这样试试:

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

    通过让第一个 then 返回一个承诺,它会等到您的 setTimeout 之后并以正确的顺序继续。

    编辑:作为奖励,当使用setTimeouts 时,这个助手非常有用:

    const wait = ms => () => new Promise(resolve => setTimeout(resolve,ms));
    

    你可以这样使用:

    Promise.resolve()
    .then(wait(2000))
    .then(() => {
      doSomething();
    })
    

    【讨论】:

      猜你喜欢
      • 2022-08-20
      • 2020-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 2021-08-11
      • 1970-01-01
      相关资源
      最近更新 更多