Skip to content

Promise.all / Promise.race 实现

Promise.all

描述

Promise.all() 方法接受一个 Promise 可迭代对象,返回一个新的 Promise。当所有 Promise 都成功时,新的 Promise 才会 resolve;如果任意一个 Promise 失败,新的 Promise 会 reject。

实现代码

js
Promise.myAll = function (promises) {
    const results = [];
    let completedCount = 0;

    return new Promise((resolve, reject) => {
        if (promises.length === 0) {
            resolve([]);
            return;
        }

        promises.forEach((promise, index) => {
            Promise.resolve(promise).then(
                (value) => {
                    results[index] = value;
                    completedCount++;
                    if (completedCount === promises.length) {
                        resolve(results);
                    }
                },
                (reason) => {
                    reject(reason);
                },
            );
        });
    });
};

使用示例

js
const p1 = Promise.resolve(1);
const p2 = new Promise((resolve) => setTimeout(() => resolve(2), 100));
const p3 = Promise.resolve(3);

Promise.myAll([p1, p2, p3]).then(console.log); // [1, 2, 3]

// 任意一个失败
const p4 = Promise.reject("error");
Promise.myAll([p1, p4, p3]).catch(console.log); // 'error'

Promise.race

描述

Promise.race() 方法返回一个新的 Promise,以最先 settled(fulfilled 或 rejected)的 Promise 的结果为准。

实现代码

js
Promise.myRace = function (promises) {
    return new Promise((resolve, reject) => {
        promises.forEach((promise) => {
            Promise.resolve(promise).then(
                (value) => resolve(value),
                (reason) => reject(reason),
            );
        });
    });
};

使用示例

js
const p1 = new Promise((resolve) => setTimeout(() => resolve("第一个"), 200));
const p2 = new Promise((resolve) => setTimeout(() => resolve("第二个"), 100));
const p3 = new Promise((_, reject) => setTimeout(() => reject("第三个失败"), 50));

Promise.myRace([p1, p2]).then(console.log); // '第二个'(最快)
Promise.myRace([p1, p3]).catch(console.log); // '第三个失败'

Promise.allSettled

描述

Promise.allSettled() 返回一个在所有给定 Promise 都 settled(无论成功或失败)后的 Promise。

实现代码

js
Promise.myAllSettled = function (promises) {
    const results = [];
    let completedCount = 0;

    return new Promise((resolve) => {
        if (promises.length === 0) {
            resolve([]);
            return;
        }

        promises.forEach((promise, index) => {
            Promise.resolve(promise)
                .then(
                    (value) => {
                        results[index] = { status: "fulfilled", value };
                    },
                    (reason) => {
                        results[index] = { status: "rejected", reason };
                    },
                )
                .finally(() => {
                    completedCount++;
                    if (completedCount === promises.length) {
                        resolve(results);
                    }
                });
        });
    });
};

使用示例

js
const p1 = Promise.resolve(1);
const p2 = Promise.reject("error");

Promise.myAllSettled([p1, p2]).then(console.log);
// [
//   { status: 'fulfilled', value: 1 },
//   { status: 'rejected', reason: 'error' }
// ]

Promise.any

描述

Promise.any() 返回一个新的 Promise,只要任意一个 Promise 成功就 resolve;如果全部失败才 reject。

实现代码

js
Promise.myAny = function (promises) {
    const reasons = [];
    let rejectedCount = 0;

    return new Promise((resolve, reject) => {
        if (promises.length === 0) {
            reject(new AggregateError("All promises were rejected"));
            return;
        }

        promises.forEach((promise, index) => {
            Promise.resolve(promise).then(
                (value) => resolve(value),
                (reason) => {
                    reasons[index] = reason;
                    rejectedCount++;
                    if (rejectedCount === promises.length) {
                        reject(new AggregateError(reasons));
                    }
                },
            );
        });
    });
};

使用示例

js
const p1 = Promise.reject(1);
const p2 = new Promise((resolve) => setTimeout(() => resolve(2), 100));

Promise.myAny([p1, p2]).then(console.log); // 2

// 全部失败
const p3 = Promise.reject("error1");
const p4 = Promise.reject("error2");
Promise.myAny([p3, p4]).catch((err) => console.log(err.errors));
// ['error1', 'error2']

四者对比

方法成功条件失败条件返回值
all全部成功任意一个失败所有结果的数组
race任意一个先 settled任意一个先失败最先结果
allSettled全部 settled所有状态的数组
any任意一个成功全部失败最先成功的值