Promise A+实现

343 阅读1分钟

最近在工作中,发现自己对Promise理解还是有所欠缺,所以,根据Promise A+标准,对其进行了实现,下面放上源码:

const PENDING = 'PENDING';
const REJECTED = 'REJECTED';
const FULFILLED = 'FULFILLED';

class myPromise {
    value = null;
    error = null;
    status = PENDING;

    onFulfilledCallbacks = [];
    onRejectedCallbacks = [];

    constructor(executor) {
        const resolve = value => {
            this.value = value;
            this.status = FULFILLED;
            this.onFulfilledCallbacks.forEach(fn => fn());
        };

        const reject = error => {
            this.error = error;
            this.status = REJECTED;
            this.onRejectedCallbacks.forEach(fn => fn());
        };

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

    then = (onFulfilled, onRejected) => {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
        onRejected =
            typeof onRejected === 'function'
                ? onRejected
                : error => {
                      throw error;
                  };

        const promise2 = new myPromise((resolve, reject) => {
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        const x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (err) {
                        reject(err);
                    }
                }, 0);
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (err) {
                        reject(err);
                    }
                }, 0);
            }

            if (this.status === PENDING) {
                this.onFulfilledCallbacks.push(
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (err) {
                            reject(err);
                        }
                    }, 0),
                );

                this.onRejectedCallbacks.push(
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (err) {
                            reject(err);
                        }
                    }, 0),
                );
            }
        });

        return promise2;
    };
}

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('循环引用'));
    }

    let called = false;

    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
        try {
            let then = x.then;
            if (typeof then === 'function') {
                then.call(
                    x,
                    y => {
                        if (called) return;
                        called = true;

                        resolvePromise(promise2, 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);
    }
}

new myPromise((resolve, reject) => {
    resolve(1);
}).then(res => {
   console.log(res)
});