

Promise.all() 原理解析及使用指南
source link: https://my.oschina.net/lav/blog/5227947
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Promise
对象是ECMAScript 6中新增的对象,主要将 JavaScript 中的异步处理对象和处理规则进行了规范化。前面介绍了《Promise.any() 原理解析及使用指南》,本文来介绍另一个方法 Promise.all(promises)
,能够一次并行处理多个 promise
,并且只返回一个 promise
实例, 那个输入的所有 promise
的 resolve
回调的结果是一个数组。
下面来看看 Promise.all()
是如何工作的。
1.工作原理
Promise.all()
是一个内置的辅助函数,接受一组 promise
(或者一个可迭代的对象),并返回一个promise
:
const allPromise = Promise.all([promise1, promise2, ...]);
可以使用 then
方法提取第一个 promise
的值:
allPromise.then((values) => {
values; // [valueOfPromise1, valueOfPromise2, ...]
});
也可以使用 async/await
语法:
const values = await allPromise;
console.log(values); // [valueOfPromise1, valueOfPromise2, ...]
Promise.all()
返回的 promise
被解析或拒绝的方式。
如果 allPromise
都被成功解析,那么 allPromise
将使用一个包含各个 promise
已执行完成后的值的数组作为结果。数组中 promise
的顺序是很重要的——将按照这个顺序得到已实现的值。
但是如果至少有一个 promise
被 rejected
,那么 allPromise
会以同样的原因立即 rejected
(不等待其他 promise
的执行)。
如果所有的 promise
被 rejected
,等待所有的promise
执行完成,但只会返回最先被rejected
的promise
的 reject
原因。
2. 使用指南
现在来深入介绍一下 Promise.all()
, 在这之前,先来定义 2 个简单的函数。
函数
resolveTimeout(value, delay)
将返回一个在经过delay
时间后有resolve
的promise
。
function resolveTimeout(value, delay) {
return new Promise((resolve) => setTimeout(() => resolve(value), delay));
}
函数
rejectTimeout(reason, delay)
将返回一个在经过delay
时间后有reject
的promise
。
function rejectTimeout(reason, delay) {
return new Promise((r, reject) => setTimeout(() => reject(reason), delay));
}
接下来使用上面定义的2个辅助函数来试试 Promise.all()
。
2.1 完成所有 promises
下面定义了一个 promise
数组 allPromise
,所有的 promise
都能够成功的 resolve
值,如下:
function resolveTimeout(value, delay) {
return new Promise((resolve) => setTimeout(() => resolve(value), delay));
}
const fruits = ["potatoes", "tomatoes"];
const vegetables = ["oranges", "apples"];
const allPromise = [
resolveTimeout(fruits, 2000),
resolveTimeout(vegetables, 1000),
];
const promise = Promise.all(allPromise);
// 等待... 2秒后
const list = async () => {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.log(error.errors);
}
};
list(); // [ [ 'potatoes', 'tomatoes' ], [ 'oranges', 'apples' ] ]
从上面执行的结果来看 Promise.all()
返回的 promise
的 resolve
数组是按照执行前 allPromise
的顺序组成其结果。
promise
数组的顺序直接影响结果的顺序,和promise
执行完成的先后无关。
2.2 一个 promise
被 rejected
将上面数组 allPromise
的第一个 promise
出现异常被 rejected
,如下代码:
const promise = Promise.all([
rejectTimeout(new Error("fruits is empty"), 5000),
resolveTimeout(vegetables, 1000),
]);
// 等待...
const list = async () => {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.log(error);
}
};
list(); // Error: fruits is empty
然而,在经过 5秒
之后,第一个 promise
由于异常被 rejected
,使得 allPromise
也被 rejected
,并返回跟第一个 promise
一样的错误信息:Error: fruits is empty
,即使在 1秒
后就完成的第二个 promise
的值也不被采纳。
接下来将数组 allPromise
的所有 promise
都抛出异常被 rejected
,通过定时器将 rejected
的顺序做个调整,如下:
const promise = Promise.all([
rejectTimeout(new Error("fruits is empty"), 5000),
rejectTimeout(new Error("vegetables is empty"), 1000),
]);
// 等待...
const list = async () => {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.log(error);
}
};
经过 5秒
之后完成执行,而结果显示为 Error: vegetables is empty
,不难看出 allPromise
被 rejected
的原因是最先 rejected
的promise
。
Promise.all()
的这种行为被称为快速失败,如果promise
数组中至少有一个promise
被rejected
,那么返回的promise
也被拒绝。如果promise
数组中所有的都被rejected
,那么返回的promise
被拒绝的原因是先rejected
的那一个。
Promise.all()
是并行执行异步操作并获取所有 resolve
值的最佳方法,非常适合需要同时获取异步操作结果来进行下一步运算的场合。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK