實現 Promise.resolve/reject/all/race 及例項方法 .catch/.finally

qwer ?發表於2020-01-16

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.im/post/5e0ea8…

相關文章