手写promise

// _Promise.js
// 先定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function isFunction(fn) {
    return typeof fn === 'function';
}
function isObject(ob) {
    return typeof ob === 'object';
}
function isNull(value) {
    return value === null;
}
function resolvePromise(promise, value, resolve, reject) {
    // 自己调用自己
    if (promise === value) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
    }

    // if (value instanceof _Promise) {
    //     value.then(resolve, reject);
    // } else {
    //     resolve(value);
    // }
    if (isFunction(value) || isObject(value)) {
        if (isNull(value)) {
            return resolve(value);
        }
        let then;
        try {
            then = value.then;
        } catch (err) {
            return reject(err);
        }
        if (isFunction(then)) {
            // then里面resolve 和 reject 只能有一个执行,因此加一个锁。
            let called = false;
            try {
                then.call(
                    // this 指向value
                    value,
                    // resolve
                    val => {
                        if (called) return;
                        called = true;
                        resolvePromise(promise, val, resolve, reject);
                    },
                    // reject
                    val => {
                        if (called) return;
                        called = true;
                        reject(val);
                    }
                );
            } catch (err) {
                if (called) return;
                return reject(err);
            }
        } else {
            // 如果直接是一个值,就resolve它
            return resolve(value);
        }
    } else {
        // 如果直接是一个值,就resolve它
        return resolve(value);
    }
}

// 新建 _Promise 类
class _Promise {
    constructor(executor) {
        // executor 是一个执行器,进入会立即执行
        // 并传入resolve和reject方法
        try {
            executor(this.resolve, this.reject);
        } catch (error) {
            this.reject(error);
        }
    }
    // 储存状态的变量,初始值是 pending
    status = PENDING;
    // 成功之后的值
    value = null;
    // 失败之后的原因
    reason = null;
    // 存储成功回调函数
    onFulfilledCallbackList = [];
    // 存储失败回调函数
    onRejectedCallbackList = [];
    // 更改成功后的状态
    resolve = value => {
        // 只有状态是等待,才执行状态修改
        if (this.status === PENDING) {
            // 状态修改为成功
            this.status = FULFILLED;
            // 保存成功之后的值
            this.value = value;
            // resolve里面将所有成功的回调拿出来执行
            while (this.onFulfilledCallbackList.length) {
                // Array.shift() 取出数组第一个元素,然后()调用,shift不是纯函数,取出后,数组将失去该元素,直到数组为空
                this.onFulfilledCallbackList.shift()(value);
            }
        }
    };
    // 更改失败后的状态
    reject = reason => {
        // 只有状态是等待,才执行状态修改
        if (this.status === PENDING) {
            // 状态成功为失败
            this.status = REJECTED;
            // 保存失败后的原因
            this.reason = reason;
            // resolve里面将所有失败的回调拿出来执行
            while (this.onRejectedCallbackList.length) {
                this.onRejectedCallbackList.shift()(reason);
            }
        }
    };
    then(onFulfilled, onRejected) {
        const realOnFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value;
        const realOnRejected = isFunction(onRejected)
            ? onRejected
            : reason => {
                  throw reason;
              };

        // 为了链式调用这里直接创建一个 _Promise,并在后面 return 出去
        const subPromise = new _Promise((resolve, reject) => {
            const fulfilledMicrotask = () => {
                // 创建一个微任务等待 subPromise 完成初始化
                // 开始采用的queueMicrotask来模拟微任务,但是queueMicrotask是使用promise搞得,这里就有点套娃的柑橘了,所以换成了setTimeout
                // queueMicrotask(() => {

                // });
                setTimeout(() => {
                    try {
                        // 获取成功回调函数的执行结果
                        const x = realOnFulfilled(this.value);
                        // 传入 resolvePromise 集中处理
                        resolvePromise(subPromise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            };

            const rejectedMicrotask = () => {
                // 创建一个微任务等待 subPromise 完成初始化
                setTimeout(() => {
                    try {
                        // 调用失败回调,并且把原因返回
                        const x = realOnRejected(this.reason);
                        // 传入 resolvePromise 集中处理
                        resolvePromise(subPromise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
                // queueMicrotask(() => {

                // });
            };
            const statusHandleMap = {
                [FULFILLED]: fulfilledMicrotask,
                [REJECTED]: rejectedMicrotask,
                [PENDING]: () => {
                    this.onFulfilledCallbackList.push(fulfilledMicrotask);
                    this.onRejectedCallbackList.push(rejectedMicrotask);
                }
            };
            statusHandleMap[this.status]();
            // 判断状态
            // if (this.status === FULFILLED) {
            //     fulfilledMicrotask();
            // } else if (this.status === REJECTED) {
            //     rejectedMicrotask();
            // } else if (this.status === PENDING) {
            //     // 等待
            //     // 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
            //     // 等到执行成功失败函数的时候再传递
            //     this.onFulfilledCallbacks.push(fulfilledMicrotask);
            //     this.onRejectedCallbacks.push(rejectedMicrotask);
            // }
        });

        return subPromise;
    }
    // resolve 静态方法
    static resolve(parameter) {
        console.log('value parameter');
        // 如果传入 _Promise 就直接返回
        if (parameter instanceof _Promise) {
            return parameter;
        }
        // 转成常规方式
        return new _Promise(resolve => {
            resolve(parameter);
        });
    }
    // reject 静态方法
    static reject(reason) {
        return new _Promise((resolve, reject) => {
            reject(reason);
        });
    }
}

// export { _Promise };
// module.exports = _Promise;

posted @ 2021-09-10 10:50  Tutao1995  阅读(35)  评论(0编辑  收藏  举报