本文详细解析 ES6 中 Promise.all 的使用方法及核心细节。Promise.all 用于并行执行多个异步操作,并在所有操作完成后执行回调。其结果数组的顺序与输入顺序一致。重点讨论了当某个 Promise 被 reject 时,Promise.all 的状态变化,特别是当子 Promise 拥有自定义 catch 方法时,不会触发 Promise.all 的失败回调这一关键陷阱。
Promise.all 基本用法
ES6 Promise.all 用法
Promise.all 方法允许并行执行多个异步操作,并在所有异步操作执行完毕后,再执行最终的回调函数。该方法可以将多个 Promise 实例包装成一个新的 Promise 实例。
const p = Promise.all([p1, p2, p3]);
在上述代码中,Promise.all 方法接收一个数组作为参数,其中 p1、p2、p3 均为 Promise 实例。如果传入的参数不是 Promise 实例,Promise.all 会先调用 Promise.resolve 方法将其转换为 Promise 实例,然后再进行后续处理。需要注意的是,Promise.all 的参数不一定必须是数组,但必须具有 Iterator 接口,且返回的每个成员都必须是 Promise 实例。
Promise.all 状态判定机制
新创建的 Promise 实例 p 的状态取决于 p1、p2、p3 的状态,具体分为两种情况。
- 只有当 p1、p2、p3 的状态全部变为 fulfilled 时,p 的状态才会变为 fulfilled。此时,p1、p2、p3 的返回值会组成一个数组,传递给 p 的回调函数。
- 只要 p1、p2、p3 中有一个实例被 rejected,p 的状态就会变为 rejected。此时,第一个被 reject 的实例的返回值,会传递给 p 的回调函数。
Promise.all 异常处理陷阱
然而,这里有一个需要特别注意的细节。
如果作为参数的 Promise
实例自身定义了 catch 方法,那么即使它被 rejected,也不会触发 Promise.all() 的 catch 方法。
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
在上述代码中,p1 会 resolved,p2 首先会 rejected。但是,由于 p2 拥有自己的 catch 方法,该方法返回的是一个新的 Promise 实例,p2 实际上指向了这个新实例。该新实例执行完 catch 方法后,也会变为 resolved,导致 Promise.all() 参数中的两个实例都变为 resolved。因此,会调用 then 方法指定的回调函数,而不会调用 catch 方法指定的回调函数。
如果 p2 没有自己的 catch 方法,则会调用 Promise.all() 的 catch 方法。
then 方法会将所有异步操作的结果放入一个数组中,并传递给 then 回调,即下面的 results。
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
Promise.all 异步应用示例
附:Promise.all 的异步用法
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// expected output: Array [3, 42, "foo"]总结
到此这篇关于 ES6 Promise.all 的使用方法以及其细节的文章就介绍到这了,更多相关 ES6 Promise.all 使用内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!