模拟还原Promise部分功能 Promise核心逻辑实现

  1. promise就是一个类

    在执行类的时候需要传递一个执行器进去,执行器会立即执行
  2. Promise中有三种状态,分别为成功-fulfilled 失败-rejected 等待-pending

    pending -> fulfilled

    pending -> rejected

    一旦状态确定就不可更改
  3. resolve 和 reject函数是用来更改状态的

    resolve:fulfilled

    reject:rejected
  4. then方法内部做的事情就是判断状态
    如果状态是成功,调用成功回调函数

    如果状态是失败,就调用失败回调函数

    then方法是被定义在原型对象中的
  5. then成功回调有一个参数,表示成功之后的值;then失败回调有一个参数,表示失败后的原因

// 1. 用常量定义 promise 三种状态, 能有提示

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
    constructor(executor) {
        // 捕获执行器(executor)代码执行异常时的错误
        try {
            executor(this.resolve, this.reject)
        } catch (error) {
            this.reject(error)
        }
    }

    // status 存储 promise 状态
    status = PENDING;
    // value 存成功的值
    value = undefined;
    // reason 存失败提示
    reason = undefined;
    // 为异步调用,存储成功回调。(数组形式为多次调用 .then 方法时依次存储其回调函数)
    successCallback = [];
    // 为异步调用,存储失败回调。(数组形式为多次调用 .then 方法时依次存储其回调函数)
    failCallback = [];

    // 2. 定义 resolve 成功方法
    
    resolve = (value) => {
        // 判断 promise 状态,pending 时继续执行
        if (this.status !== PENDING) return;
        // 修改 premiere 状态为成功,用于后续判断
        this.status = FULFILLED;
        // 保存成功的值
        this.value = value;
        // 循环调用多次.then的回调函数,直到清空所有的回调函数
        while (this.successCallback.length) {
            return this.successCallback.shift()();
        }
    };

    // 3. 定义 reject 失败方法
    
    reject = (reason) => {
        // 判断 promise 状态,pending 时继续执行
        if (this.status !== PENDING) return;
        // 修改 premiere 状态为成功,用于后续判断
        this.status = REJECTED;
        // 保存成功的值
        this.reason = reason;
        // 循环调用多次.then的回调函数,直到清空所有的回调函数
        while (this.failCallback.length) {
            return this.failCallback.shift()();
        }
    };

    // 4. 定义 then 方法
    
    then(successCallback, failCallback) {
        // then 方法参数可选
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => { throw reason };

        // then 方法返回一个promise对象
        let thenPromise = new MyPromise((resolve, reject) => {
            // 判断 promise 状态
            if (this.status === FULFILLED) {
                // 因为new Promise需要执行完成之后才有thenPromise,同步代码中没有thenPromise
                // 使用异步操作拿到 thenPromise
                setTimeout(() => {
                    // 如果回调中报错的话就执行reject
                    try {
                        // 创建一个变量接收 successCallback的返回值
                        let callbackValue = successCallback(this.value)

                        // 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
                        // 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
                        // 如果是其他值 则调用 resolve() 返回
                        // 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
                        // 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
                        resolvePromise(thenPromise, callbackValue, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 如果回调中报错的话就执行reject
                    try {
                        // 创建一个变量接收 failCallback的返回值
                        let callbackValue = failCallback(this.reason)

                        // 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
                        // 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
                        // 如果是其他值 则调用 resolve() 返回
                        // 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
                        // 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
                        resolvePromise(thenPromise, callbackValue, resolve, reject)		// [1] 被调方法1
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            } else {
                // 异步情况,promise 进入等待,状态不变
                // 将成功、失败的回调存起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        // 处理异步的成功错误情况
                        // 如果回调中报错的话就执行reject
                        try {
                            // 创建一个变量接收 failCallback的返回值
                            let callbackValue = successCallback(this.value)

                            // 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
                            // 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
                            // 如果是其他值 则调用 resolve() 返回
                            // 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
                            // 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
                            resolvePromise(thenPromise, callbackValue, resolve, reject)		//[1] 被调方法1
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                })
                this.failCallback.push(() => {
                    setTimeout(() => {
                        // 处理异步的成功错误情况
                        // 如果回调中报错的话就执行reject
                        try {
                            // 创建一个变量接收 successCallback的返回值
                            let callbackValue = failCallback(this.reason)

                            // 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
                            // 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
                            // 如果是其他值 则调用 resolve() 返回
                            // 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
                            // 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
                            resolvePromise(thenPromise, callbackValue, resolve, reject)		// [1] 被调方法1
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                })
            }
        })
        return thenPromise
    }

    // 5. 定义原型对象上的 finally 方法
    
    finally(callback) {
        // 不论是否成功都要调用 callback函数
        // 所以调用 then 方法获取 promise 状态,并返回其结果
        return this.then(
            (value) => {
                // 如果callback是一个异步的promise对象,我们还需要等待其执行完毕,
                // 需要用到静态方法resolve,把callback()调用之后返回的promise对象传递过去,并且执行promise,且在成功之后返回value
                return MyPromise.resolve(callback()).then(() => value)
            },
            // 失败之后调用的then方法,然后把失败的原因返回出去。
            (reason) => {
                return MyPromise.resolve(callback().then(() => { throw reason }))
            }
        )
    }

    // 6. 定义 catch 方法
    
    // 只接收错误回调
    catch (failCallback) {
        // 在内部调用 then 方法,成功回调位置传 undefined
        return this.then(undefined, failCallback)
    }

    // 7. 静态方法 all
    
    static all(array) {
        // 创建一个数组接收结果
        let result = [];
        // 创建一个计数器,确保结果数组的个数与接收的一致
        let num = 0
        // all 返回一个promise对象
        return new MyPromise((resolve, reject) => {
            // 创建一个方法,将所有的成功返回值都放入 result 数组
            function addItem(index, value) {
                result[index] = value
                num++
                // 当计数器与接收的数组长度一致时,证明一件处理完毕,输出结果数组result
                if (num === array.length) {
                    resolve(result)
                }
            }
            // 遍历接收数组的每一项
            for (let i = 0; i < array.length; i++) {
                let item = array[i]
                // 判断当前项是否为 promise 对象
                if (item instanceof MyPromise) {
                    // 如果是 promise对象,则调用 then 方法处理取得结果
                    item.then((value) => addItem(i, value), (reason) => reject(reason))
                } else {
                    // 如果为其他值则直接加入结果数组
                    addItem(i, item)
                }
            }
        })
    }

    // 8. 创建 resolve 静态方法
    
    static resolve(value) {
        // resolve 方法返回 promise对象
        // 判断接收的值时否为 promise对象,是则直接返回,不是则将接收值放入promise中返回
        if (value instanceof MyPromise) {
            return value
        }
        return new MyPromise((resolve) => resolve(value))
    }
}


// [1] 被调方法1 resolvePromise()

// 因为Mypromise 在成功、失败、异步都需要处理 callBack 返回值,
// 所以创建一个 resolvePromise 专门处理 callbackValue 相关的问题
function resolvePromise(thenPromise, callbackValue, resolve, reject) {
    // 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
    if (thenPromise === callbackValue) {
        // 如果相等了,说明return的是自己,抛出类型错误并返回
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    // 判断succValue 是否为 MyPromise 的实例对象
    if (callbackValue instanceof MyPromise) {
        // 如果是 promise 对象
        callbackValue.then(value => resolve(value), reason => reject(reason));
        // 可简写为下式
        // callbackValue.then(resolve, reject)
    } else {
        // 如果是其他值resolve返回
        resolve(callbackValue)
    }
}

module.exports = MyPromise;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值