返回
剖析 Promise-Polyfill 的源代码:从 catch 到 race 的深入探索
前端
2023-11-11 23:00:49
第一幕:catch - 抓住拒绝的奥秘
回想一下 catch 方法的使用场景,通常我们将其置于 Promise 链的最后,犹如一道坚固的防线,时刻准备着捕捉拒绝的原因。因此,catch 方法被定义在 Promise 的原型链上,让我们看看它的源代码:
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
catch 方法其实是一个简化的 then 方法,在内部它调用 then 方法,第一个参数为 undefined,表示不关心成功的值,而第二个参数就是我们传入的 onRejected 函数,用于处理拒绝的原因。
第二幕:all - 等待所有 Promise 的绽放
all 方法是 Promise 的静态方法,它可以接收一个包含 Promise 实例的数组作为参数,然后返回一个新的 Promise。这个新的 Promise 会在所有传入的 Promise 都完成后才被决议,决议的值是一个包含所有传入 Promise 的结果的数组。
Promise.all = function (iterable) {
return new Promise((resolve, reject) => {
// 初始化结果数组
const values = [];
// 计数器,追踪已完成的 Promise 个数
let count = 0;
// 遍历 Promise 数组
for (let i = 0; i < iterable.length; i++) {
// 使用 then 方法处理每个 Promise
Promise.resolve(iterable[i]).then(
(value) => {
// 将结果存储到结果数组中
values[i] = value;
// 计数器加一
count++;
// 如果所有 Promise 都已完成,则决议新的 Promise
if (count === iterable.length) {
resolve(values);
}
},
(reason) => {
// 如果其中一个 Promise 被拒绝,则立即拒绝新的 Promise
reject(reason);
}
);
}
});
};
第三幕:race - 并行任务的赛跑
race 方法也是 Promise 的静态方法,它可以接收一个包含 Promise 实例的数组作为参数,然后返回一个新的 Promise。这个新的 Promise 会在数组中第一个决议或拒绝的 Promise 后立即决议或拒绝。
Promise.race = function (iterable) {
return new Promise((resolve, reject) => {
// 遍历 Promise 数组
for (let i = 0; i < iterable.length; i++) {
// 使用 then 方法处理每个 Promise
Promise.resolve(iterable[i]).then(
(value) => {
// 如果其中一个 Promise 决议,则立即决议新的 Promise
resolve(value);
},
(reason) => {
// 如果其中一个 Promise 被拒绝,则立即拒绝新的 Promise
reject(reason);
}
);
}
});
};
结语
通过对 Promise-Polyfill 源代码的深入解析,我们揭开了 catch、all 和 race 方法的神秘面纱。它们是 Promise 生态圈中不可或缺的工具,为我们提供了捕获拒绝、汇总结果和并行执行任务的能力。