手写满足PromiseA+规范源码(下)

117 阅读1分钟

附上源码

最后附上源代码,经过promises-aplus-tests库进行promiseA+规范用例测试,所有用例Pass

const FULFILLED_STATUS = "fulfilled";
const REJECTED_STATUS = "rejected";
const PENDING_STATUS = "pending";

function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) {
        // 避免循环引用
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
    }
    let called;
    if (x !== null && (["function", "object"].includes(typeof x))) {
        // 判断当前x的类型是否为Promise
        try {
            let then = x.then;
            if (typeof then === "function") {
                then.call(x, y => {
                    if (called) return;
                    called = true;
                    // y 仍为一个promise 需要递归调用
                    resolvePromise(promise, y, resolve, reject);
                }, r => {
                    if (called) return;
                    called = true;
                    reject(r);
                })
            } else {
                resolve(x);
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
        resolve(x);
    }
}

class MyPromise {
    constructor(executor) {
        this.status = PENDING_STATUS;
        this.value = undefined;
        this.reason = undefined;
        this.onFulfillCallbacks = [];
        this.onRejectCallbacks = [];

        const resolve = (value) => {
            if (this.status === PENDING_STATUS) {
                this.status = FULFILLED_STATUS;
                this.value = value;
                this.onFulfillCallbacks.forEach(fn => fn());
            }
        }

        const reject = (reason) => {
            if (this.status === PENDING_STATUS) {
                this.status = REJECTED_STATUS;
                this.reason = reason;
                this.onRejectCallbacks.forEach(fn => fn());
            }
        }

        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
    }

    // return Promise
    then(onFulfilled, onRejected) {
        // 解决链式调用问题,then 的值传递
        onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;
        onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason };

        let promise2 = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED_STATUS) {
                // setTimeout 宏任务 延后执行 为了可以获取到promise2
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            } else if (this.status === REJECTED_STATUS) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            } else if (this.status === PENDING_STATUS) {
                this.onFulfillCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                })
                this.onRejectCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);

                })
            }
        });
        return promise2;
    }
}


// promiseA+规范测试库来验证你的promise

MyPromise.defer = MyPromise.deferred = function () {
    let dfd = {};
    dfd.promise = new MyPromise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
}
try {
    module.exports = MyPromise;
} catch (err) { }