实现 Promise.resolve/reject/all/race 及实例方法 .catch/.finally

2,473 阅读2分钟

Promise 非常好用,去处理异步问题时,可以链式调用,解决了回调地狱的问题。

  • Promise.resolve 是实现直接创建一个成功态的promise
  • Promise.reject是实现直接创建一个失败态的promise
  • Promise.all是处理一组promise对象的结果,只有当每个promise都成功时,走.then方法返回成功数组,当有一个promise失败时,直接走.catch方法返回失败原因,all可以看成旅行乘车,当乘客全都坐上时再走
  • Promise.race也是处理一组promise对象的结果,一旦有一个promise完成,无论成功失败均标记promise的完成,race可以看作是赛跑,一旦有一个完成,就返回结果
  • .catchpromise的实例方法,当返回失败态的promise时,会走该函数处理异常问题
  • .finallypromise的实例方法,无论返回成功失败,都会走该逻辑,比如当发送一个请求时展示了loading组件,无论请求成功或失败都要关闭该loading组件,否则用户将无法操作

下边介绍每个方法的实现

Promise.resolve

Promise.resolve = function (data) {
    // 1 参数是一个 Promise 实例,不做任何修改、原封不动地返回这个实例
    if (data instanceOf Promise) {
        return data
    }
    // 2 参数是一个thenable对象,将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
    if (data.then) {
        return new Promise((resolve, reject) => {
            data.then(resolve, reject)
        })
    }
    // 3 参数不是具有then方法的对象,或根本就不是对象
    // 4 不带有任何参数
    return new Promise((resolve) => {
        resolve(data)
    })
}

Promise.reject

Promise.reject = function (err) {
    return new Promise((_, reject) => {
        reject(err)
    })
}

Promise.all

Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        let count = promises.length
        let result = []
        // 遍历 promises,如果成功,count--,将成功值存入数组,如果失败直接 reject,当计数器为0时,resolve结果
        promises.forEach((promise, index) => {
            Promise.resolve(promise).then(res => {
                --count
                // 每个 promise 的结果放在其对应位置上
                result[index] = res
                if (count === 0) {
                    resolve(result)
                }
            }).catch(err => {
                reject(err)
            })
        })
    })
}

Promise.race

Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
    //  直接遍历 promises,有成功或失败都立即返回
        promises.forEach((promise) => {
            // 此处借用 Promise.resolve 将传入的每一个都 promise化,使其拥有 .then 方法
            Promise.resolve(promise).then(res => {
                resolve(res)
            }).catch(err => {
                reject(err)
            })
        })
    })
}

promise.catch

  • 实例方法写在原型上
class Promise {
    // ...
    catch(onRejected) {
        // 借助 之前实现的 .then 方法将错误信息传入该回调函数
        this.then(null, onRejected)
    }
    // ...
}

promise.finally

  • 实例方法写在原型上
class Promise {
    // ...
    // 借用 Promise.resolve方法,使得 callback执行完返回后才会继续向下,
    // 将 promise对象的原数据继续向下传递,
    // 失败数据则需要抛出供后续catch 使用
    finally(callback) {
        return this.then(data => {
            return Promise.resolve(callback()).then(() => data)
        }, err => {
            return Promise.resolve(callback()).then(() => {
                throw err
            })
        })
    }
    // ...
}

Promise 的实现 传送门 juejin.cn/post/684490…