js 手写promise

css 复制代码
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
    #status = PENDING;
    #result = undefined;
    #handler = undefined;

    constructor(executor) {
        // 不能写在外面,因为this指向会出问题
        const resolve = (data) => {
            this.#changeState(FULFILLED, data);
        }

        const reject = (err) => {
            this.#changeState(REJECTED, err);
        }
    
        try {
            executor(resolve, reject);
        } catch(err) {
            reject(err); 
        }
    }

    #changeState (status, result) {
        if (this.#status !== PENDING) {
            return;
        }
        this.#status = status;
        this.#result = result;
        this.#run();
    }

    #run () {
        console.log(this, this.#handler);
        if (this.status === PENDING) {
            return;
        }
        const { onFulfilled, onRejected, resolve, reject } = this.#handler;
        // 回调不是函数,那么将当前的promise状态透传
        // 回调是函数,将函数执行返回值作为新的值传递,状态变为成功,执行过程报错,那么状态就为失败
        if(this.#status === FULFILLED) {
            if (typeof onFulfilled === 'function') {
                try {
                    const res = onFulfilled(this.#result);
                    resolve(res);
                } catch (err) {
                    reject(err);
                }
            } else {
                resolve(this.#result);
            }
        } else {
            if (typeof onRejected === 'function') {
                try {
                    const res = onRejected(this.#result);
                    resolve(res);
                } catch (err) {
                    reject(err);
                }
            } else {
                reject(this.#result);
            }
        }
    }

    then(onFulfilled, onRejected) {
        return  new MyPromise((resolve, reject) => {
            this.#handler = { onFulfilled, onRejected, resolve, reject };
            this.#run();
        });
    }
}

const p = new Promise((resolve, reject) => {
    // setTimeout(() => {
        reject(222);
    // }, 0);
    // resolve(111);
    // throw 123;
    // setTimeout(() => {
    //     throw 123;  // 异步错误捕获不到,Promise也是一样
    // }, 0);
});

p.then((res) => {
    console.log('成功1', res);
}, (err) => {
    console.log('失败1', err);
    return 333;
}).then(1, (err) => {
    console.log('失败2', err);
}).then((res) => {
    console.log('成功3', res);
}, (err) => {
    console.log('失败3', err);
}).then((res) => {
    console.log('成功4', res);
}, (err) => {
    console.log('失败4', err);
});

const p1 = new MyPromise((resolve, reject) => {
    // setTimeout(() => {
        reject(222);
    // }, 0);
    // resolve(111);
    // throw 123;
    // setTimeout(() => {
    //     throw 123;  // 异步错误捕获不到,Promise也是一样
    // }, 0);
});

p1.then((res) => {
    console.log('成功1', res);
}, (err) => {
    console.log('失败1', err);
    return 333;
}).then(1, (err) => {
    console.log('失败2', err);
}).then((res) => {
    console.log('成功3', res);
}, (err) => {
    console.log('失败3', err);
}).then((res) => {
    console.log('成功4', res);
}, (err) => {
    console.log('失败4', err);
});

其他静态方法

css 复制代码
	static resolve(value) {
        return new MyPromise((resolve) => resolve(value));
    }

    static reject(reason) {
        return new MyPromise((resolve, reject) => reject(reason));
    }

    static all(promises) {
        // 问题关键: 什么时候要执行resolve, 什么时候要执行reject
        return new MyPromise((resolve, reject) => {
            const values = [];
            promises.forEach((promise) => {
                promise.then(
                    (res) => {
                        values.push(res);
                        if (values.length === promises.length) {
                            resolve(values);
                        }
                    },
                    (err) => {
                        reject(err);
                    },
                );
            });
        });
    }

    static allSettled(promises) {
        return new MyPromise((resolve) => {
            const results = [];
            promises.forEach((promise) => {
                promise.then(
                    (res) => {
                        results.push({ status: PROMISE_STATUS_FULFILLED, value: res });
                        if (results.length === promises.length) {
                            resolve(results);
                        }
                    },
                    (err) => {
                        results.push({ status: PROMISE_STATUS_REJECTED, value: err });
                        if (results.length === promises.length) {
                            resolve(results);
                        }
                    },
                );
            });
        });
    }

    static race(promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach((promise) => {
                promise.then(resolve, reject);
            });
        });
    }

    static any(promises) {
        // resolve必须等到有一个成功的结果
        // reject所有的都失败才执行reject
        const reasons = [];
        return new MyPromise((resolve, reject) => {
            promises.forEach((promise) => {
                promise.then(resolve, (err) => {
                    reasons.push(err);
                    if (reasons.length === promises.length) {
                        reject(new AggregateError(reasons));
                    }
                });
            });
        });
    }
相关推荐
Warren9816 分钟前
Java泛型
java·开发语言·windows·笔记·python·spring·maven
destinying17 分钟前
当部分请求失败时,前端如何保证用户体验不崩溃?
前端·javascript·程序员
仪器科学与传感技术博士19 分钟前
python:以支持向量机(SVM)为例,通过调整正则化参数C和核函数类型来控制欠拟合和过拟合
开发语言·python·算法·机器学习·支持向量机·过拟合·欠拟合
科大饭桶21 分钟前
C++入门自学Day5-- C/C++内存管理(续)
c语言·开发语言·c++
幼儿园技术家23 分钟前
Diff算法的简单介绍
前端
一只乔哇噻23 分钟前
Java,八股,cv,算法——双非研0四修之路day24
java·开发语言·经验分享·学习·算法
陈随易24 分钟前
为VSCode扩展开发量身打造的UI库 - vscode-elements
前端·后端·程序员
子壹26 分钟前
大文件分片上传
javascript·node.js
叁金Coder27 分钟前
业务系统跳转Nacos免登录方案实践
前端·javascript·nginx·nacos
蓝倾28 分钟前
京东商品销量数据如何获取?API接口调用操作详解
前端·api·fastapi