手写Promise

73 阅读2分钟
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class PromiseFaker {
    constructor(executor) {
        // promise的状态
        this.promiseStatus = PENDING;
        // promise的结果
        this.promiseResult = undefined;
        // 接受时回调函数的容器
        this.onFulfilleds = [];
        // 拒绝时回调函数的容器
        this.onRejecteds = [];
        // 抛出异常改变promise的状态
        try {
            executor(this.resolve.bind(this), this.reject.bind(this));
        } catch (e) {
            this.reject(e);
        }
    }
​
    // 1.修改状态
    // 2.设置结果值
    // 3.执行回调函数
    resolve(value) {
        if (this.promiseStatus === PENDING) {
            this.promiseStatus = FULFILLED;
            this.promiseResult = value;
            console.log(`${PENDING} => ${FULFILLED}`);
            while (this.onFulfilleds.length) {
                // promise 状态真正改变之后,再根据先入先出的顺序进行调用
                this.onFulfilleds.shift()(this.promiseResult);
            }
        }
    }
​
    // 1.修改状态
    // 2.设置结果值
    // 3.执行回调函数
    reject(error) {
        if (this.promiseStatus === PENDING) {
            this.promiseStatus = REJECTED;
            this.promiseResult = error;
            console.log(`${PENDING} => ${REJECTED}`);
            while (this.onRejecteds.length) {
                // promise 状态真正改变之后,再根据先入先出的顺序进行调用
                this.onRejecteds.shift()(this.promiseResult);
            }
        }
    }
​
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
        onRejected =
            typeof onRejected === "function"
                ? onRejected
                : reason => {
                        throw reason;
                  };
        const then_promise = new PromiseFaker((resolve, reject) => {
            const fulfillcallback = () => {
                queueMicrotask(() => {
                    try {
                        const x = onFulfilled(this.promiseResult);
                        this.resolvePromise(then_promise, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            };
            const rejectedcallback = () => {
                queueMicrotask(() => {
                    try {
                        const x = onRejected(this.promiseResult);
                        this.resolvePromise(then_promise, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            };
            if (this.promiseStatus === FULFILLED) {
                fulfillcallback();
            } else if (this.promiseStatus === REJECTED) {
                rejectedcallback();
            } else {
                this.onFulfilleds.push(fulfillcallback);
                this.onRejecteds.push(rejectedcallback);
            }
        });
        return then_promise;
    }
​
    resolvePromise(then_promise, x, resolve, reject) {
        // x的多种情况处理
        if (x === then_promise) {
            // 1. x 是和 then_promise 是同一个对象
            return reject(new TypeError("禁止循环引用"));
        } else if (x instanceof PromiseFaker) {
            // 2. x 是一个 promise
            if (x.promiseStatus === FULFILLED) {
                resolve(x.promiseResult);
                return;
            }
            if (x.promiseStatus === REJECTED) {
                reject(x.promiseResult);
                return;
            }
            x.then(
                y => {
                    this.resolvePromise(then_promise, y, resolve, reject);
                },
                r => reject(r)
            );
        } else if ((x !== null && typeof x === "object") || typeof x === "function") {
            // 3. x 是一个对象或者函数(函数也是对象),这里要排除掉 null,null 要归为第四种情况
            let hascalled = false;
            try {
                const then = x.then;
                if (typeof then === "function") {
                    then.call(
                        x,
                        y => {
                            if (hascalled) return;
                            hascalled = true;
                            this.resolvePromise(then_promise, y, resolve, reject);
                        },
                        r => {
                            if (hascalled) return;
                            hascalled = true;
                            reject(r);
                        }
                    );
                } else {
                    if (hascalled) return;
                    hascalled = true;
                    resolve(x);
                }
            } catch (e) {
                if (hascalled) return;
                hascalled = true;
                return reject(e);
            }
        }
    }
}
​
// 链式调用没问题 异步注册没问题
var p = new PromiseFaker(function (resolve, reject) {
    setTimeout(() => {
        return resolve(1000);
    }, 2000);
});
​
// //  执行顺序和原生一样,也是微任务也没问题
setTimeout(() => {
    console.log("定时器");
});
let p = new PromiseFaker(function (resolve, reject) {
    console.log(22);
    resolve(1000);
});
​
p.then(function (res) {
    console.log(res);
});
​
console.log(1);
​
p.then(function (res) {
    console.log(res);
});