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));
                    }
                });
            });
        });
    }
相关推荐
我不是疯子是傻子11 分钟前
串口通信数据帧粘包拆包再进化:基于 Qt 的滑动窗口与 CRC 校验实战
开发语言·qt
程序员老陆19 分钟前
Qt中实现窗口真全屏(覆盖Windows任务栏)
开发语言·windows·qt
愚公搬代码20 分钟前
【愚公系列】《Web应用安全》001-VMware的安装
前端·安全
xiaohaiAIgeo20 分钟前
【2026年】HG/T 20656-2024化工暖通空调设计规范:新版标准的变化与影响
java·前端·javascript·科普知识
立少→万能汉编22 分钟前
用“立少→超文本”写静态网页,标签<倍>
服务器·前端·javascript
weixin_4316004431 分钟前
NestJS 入门(7):生命周期钩子——构造函数和 `OnModuleInit` 差在哪?
前端·后端·学习·node.js·nest.js
霸道流氓气质1 小时前
Java中信号量(Semaphore):从本地到分布式
java·开发语言·分布式
你挚爱的强哥1 小时前
【chromeDownload】自定义组件:多用于登录框底部提供下载Chrome谷歌浏览器的链接
前端·vue.js·chrome
路溪非溪1 小时前
Python语言的执行流程总结
开发语言·python
cindershade1 小时前
用原生 HTML5 视频与 Canvas 实现浏览器端视频抽帧封面
前端