使用 Promise.all 可以同时执行多个 promise,并在所有 promise 都完成(即所有 promise 都 fulfilled 或有至少一个 promise rejected)后返回结果。但是,如果其中有一个 promise 被 reject,Promise.all 就会立即终止,并返回一个拒绝的 promise。
这种行为有时可能会带来麻烦,因为在某些情况下我们需要知道所有 promise 的状态,而不仅仅是它们中的一些。
在本文中,我们将讨论如何解决 Promise.all 遇到 reject 只执行部分 promise 的问题。
使用 Promise.allSettled
ES2020 引入了 Promise.allSettled 方法,该方法会执行所有的 promise,并等待所有 promise 都 settled(已完成,即 fulfilled 或 rejected),然后返回一个数组,该数组包含每个 promise 的状态和结果。
Promise.allSettled 返回的数组的每个元素都是一个包含以下两个键的对象:
status
:表示 promise 的状态,可以是"fulfilled"
或"rejected"
value
或reason
:分别表示 promise fulfilled 的结果和 rejected 的原因
以下是 Promise.allSettled 的示例代码:
const promise1 = Promise.resolve(3); const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'Error Occurred')); const promise3 = new Promise(resolve => setTimeout(resolve, 200, 'foo')); Promise.allSettled([promise1, promise2, promise3]) .then(results => console.log(results));
上面代码中,promise2
是个 rejected 的 promise,但是 Promise.allSettled 仍然会等待所有 promise 都 settled,然后返回一个数组,该数组包含每个 promise 的状态和结果:
[ { status: 'fulfilled', value: 3 }, { status: 'rejected', reason: 'Error Occurred' }, { status: 'fulfilled', value: 'foo' } ]
使用 Promise.allSettled 可以确保我们处理了所有 promise 的状态,并避免了因为某个 promise 被 reject 导致我们无法获取所有 promise 的状态的情况。
但是,我们可能仍然需要利用 Promise.all 的并行特性,以实现更高效的编程。
手动计数器
我们可以手动跟踪所有 promise 的状态,并在所有 promise settled 后自己返回一个数组。
以下是手动计数器的示例代码:
-- -------------------- ---- ------- -------- -------------------------------- - --- -------------- - -- --- ------------- - -- ----- ------- - --- ------ --- ----------------- -- - -------------------------- ------ -- - ------------------ -- - ----------------- -------------- - - ------- ------------ ----- -- -- --------------- - ------------- --- ---------------- - ----------------- - --------------- -- - ---------------- -------------- - - ------- ----------- ------ -- -- --------------- - ------------- --- ---------------- - ----------------- - -- --- --- - ----- -------- - ------------------- ----- -------- - --- ----------------- ------- -- ------------------ ---- ------ ------------ ----- -------- - --- --------------- -- ------------------- ---- -------- --------------------------------- --------- ---------- ------------- -- ----------------------
上面代码中,我们创建了一个 Promise 对象,并在这个对象中对所有 promise 的状态进行了跟踪。当每个 promise 完成时,我们按照其状态更新计数器和结果数组。在所有 promise 都 settled(已完成,即 fulfilled 或 rejected)后,我们能够返回一个数组,该数组包含每个 promise 的状态和结果。
这种方法手动维护计数器会比 Promise.allSettled 更冗长且容易出错,但在某些情况下,这可能是必须的。
结论
在某些情况下,我们需要知道所有 promise 的状态,并且不想因为某个 promise 被 reject 而失去对其他 promise 状态的跟踪。对于这种情况,我们可以使用 Promise.allSettled。
但有时我们需要更高效地处理多个 promise。在这种情况下,我们可能需要手动跟踪所有 promise 的状态,并在所有 promise settled 后自己返回一个数组。
虽然我们可以使用这两种方法处理 Promise.all 遇到 reject 只执行部分 promise 的问题,但我们应该选择适合我们特定情况的方法。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67188adfad1e889fe22c56f1