Promise 工具箱:手写实现静态方法的完全指南

前言

📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步!

🍅 个人主页:************************************************************南木元元****************************************************************


Promise有很多静态方法,本文就来分享下如何实现这些静态方法。

目录

静态方法

实现Promise.resolve和Promise.reject

实现Promise.all

实现Promise.allSettled

实现Promise.race

实现Promise.any

实现finally实例方法

结语


静态方法

静态方法是指直接定义在类上的方法,而不是定义在类实例上的方法。它们可以通过类本身调用,而不需要创建类的实例。静态方法通常用于用于在类级别上操作数据和提供一些实用功能,而不需要实例化对象。比如,可以在 Math 类中定义一些数学计算相关的静态方法。

在上文中,我们已经实现了Promsie中最重要的resolve、reject和then方法,但上文实现的代码是不支持直接使用MyPromise.resolve和MyPromise.reject这种形式的。我们可以在Promise 类上通过static关键字直接定义静态方法,来允许对多个 Promise 对象进行操作或直接创建新的 Promise,而无需实例化一个新的 Promise 对象。

实现Promise.resolve和Promise.reject

MDN上对**Promise.resolve()和Promise.reject()的定义:**

1.Promise.resolve() 静态方法将给定的值转换为一个 Promise。如果该值本身就是一个 Promise,那么该 Promise 将被返回;如果该值是一个thenable对象,Promise.resolve() 将调用其then() 方法及其两个回调函数;否则,返回的 Promise 将会以该值兑现。

2.Promise.reject() 静态方法返回一个已拒绝(rejected)的Promise 对象,拒绝原因为给定的参数。

javascript 复制代码
class MyPromise {

    ...

    // resolve 静态方法,返回一个以给定值解析后的Promise对象
    static resolve (param) {
        // 1.传参为Promise,直接返回
        if (param instanceof MyPromise) return param;
        
        // 2.直接返回以该值为成功状态的promise对象
        return new MyPromise(resolve =>  {
            resolve(param);
        });
    }

    // reject 静态方法,返回一个带有拒绝原因(拒绝原因为给定参数)的Promise对象
    static reject (reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason);
        });
    }
}

测试:

javascript 复制代码
MyPromise.resolve().then(() => {
    console.log(0);//0
    return MyPromise.resolve(4);
}).then((res) => {
    console.log(res)//4
})

实现Promise.all

all方法用于将多个Promise实例包装成一个新的Promise实例,只有当所有的Promise实例都成功时,新的Promise实例才会成功。

javascript 复制代码
static all(promises) {
    return new Promise(function(resolve, reject) {
        //传入参数为一个空的可迭代对象,直接resolve
        if (promises.length === 0) {
            resolve([]);
        } else {
            const res = [];
            let count = 0;
            for (let i = 0; i < promises.length; i++) {
                //为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
                Promise.resolve(promises[i]).then((data) => {
                    res[i] = data;
                    count++;
                    if (count === promises.length) {
                        resolve(res);//如果所有Promise都成功,则返回成功结果数组
                    }
                }).catch((err) => {
                    reject(err);//如果有一个Promise失败,则返回这个失败结果
                });
            }
        }
    })
}

测试:

javascript 复制代码
const promise1 = MyPromise.resolve(3);
const promise2 = 42;
const promise3 = new MyPromise((resolve, reject) => {
    setTimeout(resolve, 100, "foo");
});

MyPromise.all([promise1, promise2, promise3]).then((values) => {
    console.log(values); //[3, 42, "foo"]
});

实现Promise.allSettled

Promise.allSettled跟Promise.all类似, 唯一的不同在于, 其不会进行短路, 也就是说当Promise全部处理完成后我们可以拿到每个Promise的状态,而不管其是否处理成功。

当有多个彼此不依赖 的异步任务成功完成时,或者您总是想知道每个Promise的结果时,通常使用它。如果任务相互依赖,或者如果你想立即拒绝其中任何任务Promise.all()方法更合适。

javascript 复制代码
static allSettled(promises) {
    return new Promise(function(resolve, reject) {
        //传入参数为一个空的可迭代对象,直接resolve
        if (promises.length === 0) {
            resolve([]);
        } else {
            const res = [];
            let count = 0;
            for (let i = 0; i < promises.length; i++) {
                //为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
                Promise.resolve(promises[i]).then((data) => {
                    res[i] = {status: 'fulfilled', value: data};
                    count++;
                    if (count === promises.length) {
                        resolve(res);//如果所有Promise都成功,则返回成功结果数组
                    }
                }).catch((err) => {
                    //失败的时候,不直接返回,而是也把当前状态保存到数组中,等执行完毕时一起返回该数组
                    res[i] = {status: 'rejected', value: err};
                    count++;
                    if (count === promises.length) {
                        resolve(res);
                    }
                });
            }
        }
    })
}

测试:

javascript 复制代码
MyPromise.allSettled([
    MyPromise.resolve(33),
    new MyPromise((resolve) => setTimeout(() => resolve(66), 0)),
    99,
    MyPromise.reject(new Error("an error"))
]).then((values) => {
    console.log(values);
});

实现Promise.race

race 的实现:只要有一个 promise 执行完,直接 resolve 并停止执行。

javascript 复制代码
static race(promises) {
    return new Promise(function(resolve, reject) {
        //传入参数为一个空的可迭代对象,直接resolve
        if (promises.length === 0) {
            resolve([]);
        } else {
            for (let i = 0; i < promises.length; i++) {
                //为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
                Promise.resolve(promises[i]).then((data) => {
                    resolve(data); //返回最快的结果
                }).catch((err) => {
                    reject(err); //返回最快的结果
                });
            }
        }
    })
}

测试:

javascript 复制代码
const promise1 = new MyPromise((resolve, reject) => {
    setTimeout(resolve, 500, 'one');
});
const promise2 = new MyPromise((resolve, reject) => {
    setTimeout(resolve, 100, 'two');
});
MyPromise.race([promise1, promise2]).then((value) => {
    console.log(value);	//two
});

实现Promise.any

Promise.any() 静态方法会在任意一个传入的 Promise 成功时,返回该成功的结果。如果所有传入的 Promise 都被拒绝(即失败),它会以AggregateError的形式被拒绝,其中包含所有被拒绝的原因。

javascript 复制代码
static any(promises) {
    return new Promise(function (resolve, reject) {
        //传入参数为一个空的可迭代对象,直接resolve
        if (promises.length === 0) {
            resolve([]);
        } else {
            let count = 0;
            for (let i = 0; i < promises.length; i++) {
                //为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
                Promise.resolve(promises[i])
                .then((data) => {
                    resolve(data); //有一个Promise成功,就返回那个结果
                })
                .catch((err) => {
                    count++;
                    if (count === promises.length) {
                    //当所有输入Promise都被拒绝时,会以一个包含拒绝原因数组的AggregateError拒绝,AggregateError对象代表了包装了多个错误对象的单个错误对象
                    reject(new AggregateError('All promises were rejected')); //所有Promise都失败,就报错
                    }
                });
            }
        }
    });
}

实现finally实例方法

无论Promise是成功还是失败,都会调用finally方法,执行 finally 中传入的函数,并且将值原封不动的往下传,以保证可以继续链式调用。

javascript 复制代码
MyPromise.prototype.finally = function (callback) {
    // 调用then方法,传入两个相同的处理函数,返回一个新的 Promise 对象(保证链式调用)
    return this.then(
        value => {
            // 创建一个新的Promise实例,确保异步执行callback
            return MyPromise.resolve(callback()).then(() => value);
        },
        reason => {
            // 创建一个新的Promise实例,确保异步执行callback
            return MyPromise.resolve(callback()).then(() => { throw reason; });
        }
    );
}

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~

相关推荐
阿伟来咯~25 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端30 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱33 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai42 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨43 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry3 小时前
JS常用数组方法 reduce filter find forEach
javascript
ZL不懂前端4 小时前
Content Security Policy (CSP)
前端·javascript·面试