符合promise/A+的Mypromise

14 阅读1分钟
class MyPromise {

    constructor(executor) {
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        const fulfill = (v) => {
            if (this.state !== 'pending') return;
            this.state = 'fulfilled';
            this.value = v;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value));

        };

        const rejectFinal = (r) => {
            if (this.state !== 'pending') return;
            this.state = 'rejected';
            this.reason = r;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason));
        };

        const resolve = (value) => {
            try {
                resolvePromise(this, value, fulfill, rejectFinal);
            } catch (err) {
                rejectFinal(err);
            }
        };

        const reject = rejectFinal;

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

    then(onFulfilled, onRejected) {
        const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v;
        const realOnRejected = typeof onRejected === 'function' ? onRejected : (r) => { throw r; };

        const promise2 = new MyPromise((resolve, reject) => {
            const handle = (fn, val) => {
                queueMicrotask(() => {
                    try {
                        const x = fn(val);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (err) {
                        reject(err);
                    }
                });
            };

            if (this.state === 'fulfilled') {
                handle(realOnFulfilled, this.value);
            } else if (this.state === 'rejected') {
                handle(realOnRejected, this.reason);
            } else {
                this.onFulfilledCallbacks.push((value) => handle(realOnFulfilled, value));
                this.onRejectedCallbacks.push((reason) => handle(realOnRejected, reason));
            }
        });

        return promise2;
    }


    // static resolve(parameter) {
    //     // 如果传入 MyPromise 就直接返回
    //     if (parameter instanceof MyPromise) {
    //         return parameter;
    //     }

    //     // 转成常规方式
    //     return new MyPromise(resolve => {
    //         resolve(parameter);
    //     });
    // }

    // // reject 静态方法
    // static reject(reason) {
    //     return new MyPromise((resolve, reject) => {
    //         reject(reason);
    //     });
    // }
}


function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise'));
    }
    if (x && (typeof x === 'object' || typeof x === 'function')) {
        let called = false;
        try {
            const 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 (err) {
            if (called) return;
            called = true;
            reject(err);
        }
    } else {
        resolve(x);
    }
}


module.exports = MyPromise;