给定一组Promise,如何在确保所有Promise成功解析的同时,强行解决最后一个Promise的响应?

时间:2017-09-12 04:32:53

标签: javascript ecmascript-6 promise es6-promise

Promise One (resolves in 200ms)
Promise Two (resolves in 400ms)
Promise Three (resolves in 1000ms)
Promise Four (resolves in 300ms)
Promise Five (resolves in 500ms)

这些承诺将按以下顺序解决

0 - Requests Start
100
200 - Promise One
300 - Promise Four
400 - Promise Two
500 - Promise Five (Most recent application state)
600
700
800
900
1000 - Promise Three (Stagnant application state)

鉴于在我的应用程序中,Promises的响应决定了应用程序状态,当较旧的Promise比较新的Promise解析得慢时,我的应用程序状态将停滞不前。

一个潜在的实现是在上一个请求完成之前不会启动下一个请求,但这会大大延长用户进度。

编辑:

我可能遗漏了一些必要的背景。我什么都不知道何时会添加Promise。 Promise.all在启动后无法添加项目,所以Promise.all可能不适合我。

对于更正常的用例,提供的答案可能会很好用,但不幸的是我的API有点过于健谈。

3 个答案:

答案 0 :(得分:2)

所以你希望所有的承诺能够真正完成,但只有最新承诺才能继续前进?

Promise.all([p1, p2, p3, p4, p5]) // resolves when all promises have resolved
.then((results) => {
    // results is an array of resolved values
})

Promise.all()会为你工作吗?请记住,如果任何承诺拒绝,它就会拒绝。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

答案 1 :(得分:1)

创建一个新的promise,当所有其他promise都已解析时(使用Promise.all完成)解析,然后链接另一个promise,该promise使用发送到Promise.all的iterable的最后一个元素的值进行解析

const pTimeout = (value, timeout) => 
  new Promise(resolve => setTimeout(resolve, timeout, value))

// takes the same arguments as Promise.all but resolves with the
// resolution value of the last element
function resolveWithLast (promises) {
  return Promise.all(promises)
    .then(results => results.pop())
}

resolveWithLast([
  pTimeout(1, 200),
  pTimeout(2, 400),
  pTimeout(3, 1000),
  pTimeout(4, 300),
  pTimeout(5, 500)
])
  .then(value => console.log(value))

答案 2 :(得分:1)

使用ES2017 async / await,您可以通过执行以下操作来提高@MauricioPoppe's answer的可读性:

const pTimeout = (value, timeout) => 
  new Promise(resolve => setTimeout(resolve, timeout, value))

// takes the same arguments as Promise.all but resolves with the
// resolution value of the last element
async function resolveWithLast (promises) {
  const results = await Promise.all(promises)
  return results.pop()
}

resolveWithLast([
  pTimeout(1, 200),
  pTimeout(2, 400),
  pTimeout(3, 1000),
  pTimeout(4, 300),
  pTimeout(5, 500)
]).then(value => console.log(value))