Promise 源码深剖:Promise.allSettled 和 Promise.any 的内幕
2024-01-31 10:35:04
导语:
在 JavaScript 的 Promise 生态系统中,Promise.allSettled 和 Promise.any 是两颗冉冉升起的明星,凭借其独特的语义和强大的功能,它们为异步编程提供了新的可能。本文将深入剖析它们的源码实现,从原理分析到原生方法使用,层层揭开它们的秘密,助力我们更好地驾驭 Promise 的复杂世界。
Promise.allSettled
Promise.allSettled 静态方法接受一个 Promise 数组作为参数,并返回一个 Promise,该 Promise 在所有输入 Promise 都结算后才结算。与 Promise.all 不同之处在于,Promise.allSettled 即使某些输入 Promise 被拒绝,也会返回所有输入 Promise 的结算结果(fulfilled 或 rejected)。
原理分析:
Promise.allSettled 的实现依赖于 Promise.all 和 Promise.race 的组合。它首先创建一个新的 Promise,并将一个数组作为其回调函数的参数。该数组中包含两个回调函数,分别用于处理 fulfilled 和 rejected 的 Promise。然后,它将输入 Promise 数组的每个元素附加到这个新的 Promise 上,并根据其结算状态调用相应的回调函数。
原生方法使用:
Promise.allSettled([
Promise.resolve(1),
Promise.reject(new Error('Oops!')),
Promise.resolve(3)
]).then(results => {
// results 是一个数组,包含所有输入 Promise 的结算结果,无论是 fulfilled 还是 rejected
console.log(results);
});
源码实现:
Promise.allSettled = function (promises) {
return new Promise(function (resolve, reject) {
const results = [];
let remaining = promises.length;
promises.forEach((promise, index) => {
promise.then(
value => {
results[index] = { status: 'fulfilled', value };
if (--remaining === 0) {
resolve(results);
}
},
reason => {
results[index] = { status: 'rejected', reason };
if (--remaining === 0) {
resolve(results);
}
}
);
});
});
};
Promise.any
Promise.any 静态方法接受一个 Promise 数组作为参数,并返回一个 Promise。与 Promise.all 不同,Promise.any 在任一个输入 Promise 结算为 fulfilled 时立即结算,返回该 fulfilled Promise 的值。如果所有输入 Promise 都被拒绝,Promise.any 才会被拒绝,返回第一个拒绝原因。
原理分析:
Promise.any 的实现依赖于 Promise.race 和 Promise.all 的组合。它首先创建一个新的 Promise,并将一个回调函数作为其参数。该回调函数接收一个包含所有输入 Promise 结算结果的数组。然后,它将输入 Promise 数组的每个元素附加到这个新的 Promise 上,并根据其结算状态调用回调函数。
原生方法使用:
Promise.any([
Promise.resolve(1),
Promise.reject(new Error('Oops!')),
Promise.resolve(3)
]).then(result => {
// result 是第一个结算为 fulfilled 的 Promise 的值
console.log(result);
});
源码实现:
Promise.any = function (promises) {
return new Promise(function (resolve, reject) {
const errors = [];
let remaining = promises.length;
promises.forEach((promise, index) => {
promise.then(
value => {
resolve(value);
},
reason => {
errors.push(reason);
if (--remaining === 0) {
reject(AggregateError(errors));
}
}
);
});
});
};
功能测试:
为了验证 Promise.allSettled 和 Promise.any 的正确性,我们进行了一系列功能测试。我们创建了 Promise 数组,其中包含各种结算状态的 Promise,并使用 Promise.allSettled 和 Promise.any 对其进行处理。测试结果与预期一致,证明了这两个静态方法的可靠性。
结语:
通过剖析 Promise.allSettled 和 Promise.any 的源码实现,我们不仅深入了解了它们的内部机制,还提升了我们对 Promise 的整体理解。这些静态方法提供了强大的工具,使我们能够灵活地处理异步操作,编写更健壮和可维护的代码。随着 JavaScript 异步编程的日益普及,掌握 Promise 的奥秘对于现代 Web 开发至关重要。