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));
                    }
                });
            });
        });
    }
相关推荐
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-05-21
前端·人工智能·经验分享·chatgpt·html
怕浪猫1 小时前
Electron 开发实战(一):从零入门核心基础与环境搭建
前端·electron·ai编程
杜子不疼.2 小时前
【C++ AI 大模型接入 SDK】 - DeepSeek 模型接入(上)
开发语言·c++·chatgpt
加号32 小时前
【C#】 串口通信技术深度解析及实现
开发语言·c#
小鹏linux2 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
sycmancia2 小时前
Qt——编辑交互功能的实现
开发语言·qt
石山代码3 小时前
C++ 内存分区 堆区
java·开发语言·c++
前端若水3 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Bigger3 小时前
mini-cc:一个轻量级 AI 编程助手的诞生
前端·ai编程·claude
无风听海3 小时前
C# 隐式转换深度解析
java·开发语言·c#