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));
                    }
                });
            });
        });
    }
相关推荐
此生决int6 分钟前
深入理解C++系列(04)——类和对象(下)
开发语言·c++
MrDJun14 分钟前
分享一款免费实用的网页变动监控工具:PageWatch.tech
前端·javascript·vue.js
米码收割机15 分钟前
【web】邻里悦站—社区便民服务平【独一无二】(源码+说明文档)
前端
Yeauty19 分钟前
你那条 ffmpeg 命令,一键翻成 Rust builder 代码
开发语言·rust·ffmpeg
程序员爱钓鱼24 分钟前
Rust Option 详解:安全处理“可能存在,也可能不存在”的值
前端·后端·rust
程序员爱钓鱼25 分钟前
Go Modules 包管理详解:go.mod、go.sum 与依赖管理
前端·后端·go
鱼香鱼香rose29 分钟前
java-2
java·开发语言·python
qq_589666059 小时前
TypeScript 完整入门教程
前端·javascript·typescript
星栈独行10 小时前
翻完 Pi 源码:它和 Codex、Claude Code 有何不同
开发语言·javascript·人工智能·程序人生
qq_4480111611 小时前
C语言中的变量和函数的定义与声明
android·c语言·开发语言