手写Promise总结(源码+类方法封装+关键性问题列举)

前言:前面几篇文章我们对Promise进行了一个手写的封装,也提及到了一些有关方法的关键问题和执行机制,以及Promise的执行机制,也分别从异步和同步方向进行了考量。下面我就列举出有关Promise以及Promise相关方法的一些关键性问题,之后会给出完整的手写Promise源码,以及类封装的源码。

关键性问题:

1. 串联多个任务

简单来讲就是 通过 then方法来链式调用多个任务(异步) 值得注意的是 then 方法链式调用的时候 需要等上一个then方法结束返回了之后才会调用下一个

2. 改变状态和指定回调函数谁先谁后的问题

都有可能  正常情况(异步任务)下是先指定回调再改变状态,但也可以先改变状态再指定回调(同步任务)                                                                                                                                                那么 如何先改变状态再执行回调?                                                                                                 在执行器中直接调用 resolve()  reject()   (同步任务时) 延长事件才调用 then()                                  什么时候才能得到数据                                                                                                                    说白了回调函数调用之后就能拿到数据  不管是先改变状态还是后改变状态

3. 能否执行多个回调

当promise改变为对应状态时都会调用

4. 如何修改Promise对象的状态

调用 resolve 函数   将状态转变为  fullfilled / resolved,调用 reject 函数   将状态转变为   rejected,抛出错误

5. 如何中断Promise链

有且只有一个方法,返回一个 没有改变状态的 即 状态为 pending 的 promise 对象

6. 异常穿透

当使用 Promise 的 then 链式调用时 ,可以在最后指定失败的回调, 前面任何操作出现了异常都会传到最后失败的回调中去处理,值传递同理异常穿透

7. then方法返回的结果由什么决定

抛出错误   then方法返回的结果为 失败的promise 失败的值为 抛出的错误,返回的结果为 非promise类型的值  then方法返回的则会是成功的promise对象 值为 返回的 非promise的值,返回的结果为 promise 对象 then方法返回的结果的promise的状态由该promise对象决定

正常手写封装的Promise源码:

function Promise(executor) {
    //添加状态属性 和 结果属性
    this.PromiseState = "pending"
    this.PromiseResult = null
    // 添加一个对象 用来存储 实例的回调函数
    this.callbacks = []
    // 保存 实例对象的 this
    const _this = this
    // 声明内部函数
    function resolve(data) {
        // 判断状态 如果状态已经改变了 则不能再次调用函数改变状态
        if (_this.PromiseState !== "pending") return
        // 调用函数 修改Promise状态为 resolved || fulfilled
        _this.PromiseState = "fulfilled"
        // 生成 结果
        _this.PromiseResult = data
        // 异步情况
        // 状态改变  调用实例的回调函数
        setTimeout(() => {
            _this.callbacks.forEach(item => {
                item.onResolved(data)
            })
        });
    }
    function reject(data) {
        // 判断状态 如果状态已经改变了 则不能再次调用函数改变状态
        if (_this.PromiseState !== "pending") return
        // 调用函数 修改Promise状态为 rejected
        _this.PromiseState = "rejected"
        // 生成 结果
        _this.PromiseResult = data
        // 异步情况
        // 状态改变  调用实例的回调函数
        setTimeout(() => {
            _this.callbacks.forEach(item => {
                item.onRejected(data)
            })
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject)
    } catch (e) {
        // 修改Promise状态为 rejected
        reject(e)
    }

}

Promise.prototype.then = function (onResolved, onRejected) {
    const self = this
    // 判断回调函数参数
    if (typeof onRejected !== "function") {
        onRejected = reason => {
            throw reason
        }
    }
    if (typeof onResolved !== "function") {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        const self = this
        // 封装函数(重复代码)
        function callback(type) {
            try {
                // 执行成功的回调函数
                let result = type(self.PromiseResult)
                // 判断
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(result)
                }
            } catch (e) {
                reject(e)
            }
        }
        // 判断当前实例对象的Promise状态 依据状态调用相应的函数
        if (this.PromiseState === "fulfilled" || this.PromiseState === "resolved") {
            setTimeout(() => {
                callback(onResolved)
            });
        }
        if (this.PromiseState === "rejected") {
            setTimeout(() => {
                callback(onRejected)
            });
        } 
        // 当状态未发生改变的时候 ,将回调函数保存,等到状态改变时再调用
        if (this.PromiseState === "pending") {
            // 当有多个回调时  有多少个会调 都要保存 ,
            // 所以这里  咱们所有的实例的方法都压入一个数组中
            this.callbacks.push({
                onResolved: function () {
                    callback(onResolved)
                },
                onRejected: function () {
                    callback(onRejected)
                }
            })
        }
    })
}

// 添加 catch 方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
}

// 添加 resolve 方法
Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(v => {
                resolve(v)
            }, r => {
                reject(r)
            })
        } else {
            // 传入的参数不是一个promise对象,直接修改状态为成功,值为传入的值
            resolve(value)
        }
    })
}

// 添加 reject 方法
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason)
    })
}

// 添加 all 方法
Promise.all = function (promises) {
    // 返回的结果为promise对象
    return new Promise((resolve, reject) => {
        // 声明计数器
        let count = 0;
        // 声明返回结果存放的数组
        let arr = []
        // 遍历
        for (let i = 0; i < promises.length; i++) {
            // 当计数器的值等于promise的长度时 , 表示传入的promises中
            // 所有的promise对象都是成功的,此时才需要改变返回的promise
            // 的状态为成功,否则,计数器加一(count++)
            promises[i].then(v => {
                count++
                arr[i] = v
                if (count === promises.length) {
                    resolve(arr)
                }
            }, r => {
                reject(r)
            })
        }
    })
}

// 添加 race 方法
Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                resolve(v)
            }, r => {
                reject(r)
            })
        }
    })
}

通过类封装的Promise源码:

// class 版本封装
class Promise {
    // 构造方法
    constructor(executor) {
        //添加状态属性 和 结果属性
        this.PromiseState = "pending"
        this.PromiseResult = null
        // 添加一个对象 用来存储 实例的回调函数
        this.callbacks = []
        // 保存 实例对象的 this
        const _this = this
        // 声明内部函数
        function resolve(data) {
            // 判断状态 如果状态已经改变了 则不能再次调用函数改变状态
            if (_this.PromiseState !== "pending") return
            // 调用函数 修改Promise状态为 resolved || fulfilled
            _this.PromiseState = "fulfilled"
            // 生成 结果
            _this.PromiseResult = data
            // 异步情况
            // 状态改变  调用实例的回调函数
            setTimeout(() => {
                _this.callbacks.forEach(item => {
                    item.onResolved(data)
                })
            });
        }
        function reject(data) {
            // 判断状态 如果状态已经改变了 则不能再次调用函数改变状态
            if (_this.PromiseState !== "pending") return
            // 调用函数 修改Promise状态为 rejected
            _this.PromiseState = "rejected"
            // 生成 结果
            _this.PromiseResult = data
            // 异步情况
            // 状态改变  调用实例的回调函数
            setTimeout(() => {
                _this.callbacks.forEach(item => {
                    item.onRejected(data)
                })
            });
        }
        try {
            // 同步调用 【执行器函数】
            executor(resolve, reject)
        } catch (e) {
            // 修改Promise状态为 rejected
            reject(e)
        }
    }

    // then 方法封装
    then(onResolved, onRejected) {
        const self = this
        // 判断回调函数参数
        if (typeof onRejected !== "function") {
            onRejected = reason => {
                throw reason
            }
        }
        if (typeof onResolved !== "function") {
            onResolved = value => value
        }
        return new Promise((resolve, reject) => {
            const self = this
            // 封装函数(重复代码)
            function callback(type) {
                try {
                    // 执行成功的回调函数
                    let result = type(self.PromiseResult)
                    // 判断
                    if (result instanceof Promise) {
                        result.then(v => {
                            resolve(v)
                        }, r => {
                            reject(r)
                        })
                    } else {
                        resolve(result)
                    }
                } catch (e) {
                    reject(e)
                }
            }
            // 判断当前实例对象的Promise状态 依据状态调用相应的函数
            if (this.PromiseState === "fulfilled" || this.PromiseState === "resolved") {
                setTimeout(() => {
                    callback(onResolved)
                });
            }
            if (this.PromiseState === "rejected") {
                setTimeout(() => {
                    callback(onRejected)
                });
            }
            // 当状态未发生改变的时候 ,将回调函数保存,等到状态改变时再调用
            if (this.PromiseState === "pending") {
                // 当有多个回调时  有多少个会调 都要保存 ,
                // 所以这里  咱们所有的实例的方法都压入一个数组中
                this.callbacks.push({
                    onResolved: function () {
                        callback(onResolved)
                    },
                    onRejected: function () {
                        callback(onRejected)
                    }
                })
            }
        })
    }

    // catch 方法封装
    catch(onRejected) {
        return this.then(undefined, onRejected)
    }

    // resolve 方法封装
    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            } else {
                // 传入的参数不是一个promise对象,直接修改状态为成功,值为传入的值
                resolve(value)
            }
        })
    }

    // reject 方法封装
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    // all 方法封装
    static all(promises) {
        // 返回的结果为promise对象
        return new Promise((resolve, reject) => {
            // 声明计数器
            let count = 0;
            // 声明返回结果存放的数组
            let arr = []
            // 遍历
            for (let i = 0; i < promises.length; i++) {
                // 当计数器的值等于promise的长度时 , 表示传入的promises中
                // 所有的promise对象都是成功的,此时才需要改变返回的额promise
                // 的状态为成功,否则,计数器加一(count++)
                promises[i].then(v => {
                    count++
                    arr[i] = v
                    if (count === promises.length) {
                        resolve(arr)
                    }
                }, r => {
                    reject(r)
                })
            }
        })
    }

    // race 方法封装
    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            }
        })
    }
}

以上六篇文章就是这次手写Promise剖析的全部啦

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青灯夜游/

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值