本身動手實現一個 Promise

原生Promise關鍵特性

本身實現 Promise, 首先須要瞭解 原生 Promise 的一些 關鍵特性javascript

原生 Promise的關鍵特性 整理以下:java

  • 提供一個 構造函數 - Promise, 返回一個 promise 對象數組

    promise 對象 應包含 屬性: 狀態 - PromiseStatus(pending、resolved、rejected), 值 - PromiseValuepromise

    promise 對象初始狀態pending, undefined緩存

  • 使用 構造函數 時須要傳入一個 函數類型的參數 - fnfn 須要在 promise 對象構建完成之後當即執行bash

    fn 有兩個 函數類型的參數 - resolvereject。當 fn 內部的異步操做完成 之後,調用 resolverejectpromise對象 的狀態變爲 終態(resolved / rejected)異步

    原生 Promise 中,resolverejectjavascript引擎 提供,不須要咱們提供。當咱們本身實現 promise 時,須要提供 resolvereject函數

    fn 在執行過程當中,若是 發生異常promise 對象 的狀態會變爲 rejectedui

  • resolve 用於將 promise實例對象的狀態pending 置爲 resolvedthis

    使用的時候,須要傳入一個 參數,通常爲 fn 內部異步操做返回的結果,會做爲 promise 對象的值

    若是 沒有傳參數promise 對象 的值爲 undefined

    若是傳入的參數是一個 promise 對象,那麼 傳入的 promise 對象的狀態會傳遞給當前 promise 對象, 具體狀況以下:

    • 若是 傳入的 promise 對象的狀態爲 pending,那麼 當前 promise 對象的狀態爲 pending,等到 傳入的 promise 對象的狀態變爲終態 後, 當前 promise 對象的狀態纔會變爲相應的終態當前 promise 對象的值 會使用 傳入的 promise 對象的值 更新。

    • 若是 傳入的 promise 對象的狀態爲 resolved, 那麼 當前 promise 對象的狀態會變爲 resolved值爲傳入的promise對象的值

    • 若是 傳入的 promise 對象的狀態爲 rejected, 那麼 當前 promise 對象的狀態會變爲 rejected值爲傳入的promise對象的值

  • reject 用於將 promise實例對象的狀態pending 置爲 rejected

    使用的時候,須要傳入一個 參數,通常爲 fn 內部異步操做返回的異常,會做爲 promise 對象的值。參數也可爲

    resolve 不一樣,就算傳入的參數爲 promise 對象, 也 不會影響原 promise 對象的狀態

  • promise對象的狀態 一旦發生變化成爲 終態, 就 不會再變化

  • 原型方法 - then,用於 註冊promise 對象的狀態 變爲 終態(resolved/rejected) 時調用的 callback

    then 方法在使用的使用,須要傳入兩個 函數類型的參數- onFullfilledonRejected

    promise對象 的狀態變爲 resolved 時,執行 onFullfilled。 執行 onFullfilled 時, 會傳入一個參數,該參數爲 promise 對象的值

    promise對象 的狀態變爲 rejected 時,執行 onRejected。 執行 onRejected 時, 也會傳入一個參數,該參數爲 promise 對象的值

    onFullfilledonRejected 均可覺得

    then 方法會返回一個 新的 promise 對象, 初始狀態爲 pending

    新的 promise 對象的狀態 變爲 終態 時,可能遇到的狀況以下:

    • onFullfilledonRejected 沒有 正確註冊

      沒有正確註冊,即 promise 對象 - p1 的狀態 變爲 resolved發現沒有註冊onFullfilled, 或者 promise 對象的狀態 變爲 rejected發現沒有註冊onRejected

      此時, p1.then() 返回的 promise對象-p2 的狀態爲 p1 的狀態,p2 的值也爲 p1 的值。

    • onFullfilledonRejected 正確註冊新的 promise 對象 會根據 onFullfilled / onRjected返回值 修改狀態以及更新值, 具體狀況以下:

      • 若是 返回值普通值(普通對象、數值、字符串等)新的 promise 對象 的狀態爲 resolvedpromise對象的 值 更新爲 返回值

      • 若是 沒有返回值,默認爲 return undefined新的 promise 對象 的狀態爲 resolvedpromise對象的 值 更新爲 undefined

      • 若是返回一個 promise對象 - p2,那麼 新的promise對象 - p1狀態及值 會被影響。

        p2 的狀態爲 pendingp1 的狀態爲 pending,當 p2 的狀態變爲 終態 時,p1 的狀態也變爲 對應的終態值也更新

        p2 的狀態爲 resolvedp1 的狀態也爲 resolved,值爲 p2 的值。

        p2 的狀態爲 rejectedp1 的狀態也爲 rejected,值爲 p2 的值。

  • 原型方法 - catch,用於 註冊promise 對象的狀態 變爲 rejected 時調用的 callback

    catch 方法在使用的時候,須要傳入一個 函數類型的參數- onRejected

    promise對象 的狀態變爲 rejected 時,執行 onRejected。 執行 onRejected 時, 會傳入一個參數,該參數爲 promise 對象的值

    catch 方法會返回一個 新的 promise 對象, 初始狀態爲 pending,變爲 終態 的狀況和 then 方法一致。

  • 原型方法 - finally,用於 註冊promise 對象的狀態 變爲 終態(resolved/rejected) 時調用的 callback

    finally 方法在使用的使用,須要傳入一個 函數類型的參數- callback

    promise 對象 的狀態變爲 終態(resolved/rejected) 時,執行 callbackcallback 的參數爲 , 即 callback 內部的操做不依賴 promise 對象 的值。

    finally 方法會返回一個 promise對象, 初始狀態爲 pending,變爲 終態 的狀況參照 then

    thencatch 方法中,若是 onFullfilled / onRejected 的返回值 不是 promise 對象, 那麼 返回值 會做爲 新的 promise 對象的值finally 方法會有稍許不一樣,若是 callback的返回值 不是 promise 對象, 那麼 新的 promise 對象的值原 promise 對象的值

  • 靜態方法 - Promise.resolve, 用於 快速構建 一個 promise 對象

    使用 resolve 的時候,會傳入 一個參數。參數的不一樣, 會影響 返回的 promise 對象的狀態和值,以下:

    • 參數爲一個 promise 對象,不作任何處理, 直接返回傳入的 promise 對象

    • 參數爲 thenable 對象,即具備 then 方法 的對象, 返回一個 新的 promise 對象, 狀態爲 resolved, 值爲 then方法的返回值

    • 參數爲 普通值, 即 非promise對象非thenable對象, 返回一個 新的 promise 對象, 狀態爲 resolved, 值爲 傳入的參數

    • 參數爲 , 返回一個 新的 promise 對象, 狀態爲 resolved, 值爲 undefined

  • 靜態方法 - Promise.reject,用於 快速構建 一個狀態爲 rejectedpromise 對象

    Promise.resolve 方法不一樣, 無論傳入的參數是什麼值, 返回的的 promise 對象 的狀態爲 rejected, 值爲 傳入的參數

  • 靜態方法 - Promise.all用於跟蹤多個 promise 對象的狀態變化

    all 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending

    當參數中 全部的 promise 對象的狀態 變爲 resolved 時, p1的狀態 纔會變爲 resolved,此時 p1的值 是一個 數組數組元素參數數組中各個 promise 對象的值

    參數中 只要有一個 promise 對象的狀態變爲 rejectedp1的狀態 就會變爲 rejectedp1的值第一個狀態爲 rejected 的 promise 對象的值

  • 靜態方法 - Promise.race用於跟蹤多個 promise 對象的狀態變化

    race 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending

    參數中 只要有一個 promise 對象的狀態變爲 終態p1的狀態 就會變爲 相應的狀態p1的值第一個狀態爲 終態 的 promise 對象的值

  • 靜態方法 - Promise.any用於跟蹤多個 promise 對象的狀態變化

    any 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending

    當參數中 全部的 promise 對象的狀態 變爲 rejected 時, p1的狀態 纔會變爲 rejected,此時 p1的值 是一個 數組數組元素參數數組中各個 promise 對象的值

    參數中 只要有一個 promise 對象的狀態變爲 resolvedp1的狀態 就會變爲 resolvedp1的值第一個狀態爲 resolved 的 promise 對象的值

  • 靜態方法 - Promise.allSetted用於跟蹤多個 promise 對象的狀態變化

    allSettled 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending

    當參數中 全部的 promise 對象的狀態變爲 終態p1的狀態 就會變爲 resolved, 此時 p1的值 是一個 數組數組元素參數數組中各個 promise 對象的值

  • 微任務隊列

    在一個 事件循環 中,當 promise 對象的狀態 變爲 終態時, 會開啓一個 微任務隊列, 將 對應的callback 添加到 隊列 中。 當 事件循環 中的 同步代碼 執行完成之後,開始處理 微任務隊列 中的 任務

    微任務隊列 開始工做之後, 若是有 新的 promise 對象的狀態變爲終態, 會將 對應的callback 繼續添加到 微任務隊列 中等待處理。

    微任務隊列 中的 全部任務處理完畢 之後就會被 清空,而後關閉微任務隊列,直到下一次事件循環中有 promise 對象的狀態變爲終態時從新開啓

實現 promise

根據上述 原生promise關鍵特性,咱們可本身動手逐步實現 Promise。實現過程以下:

  1. 模擬微任務隊列

    在這裏, 咱們使用 setTimeout一個數組 - queue 來模擬 微任務隊列,以下:

    let queue = [] // 任務隊列
    let flushing = false // 任務隊列未啓用
    let index = 0
    // 將任務添加到任務隊列中
    // 若是是首次將任務添加到任務隊列中,啓動任務隊列,
    //      並經過setTimeout實現同步代碼執行完成之後處理任務隊列中的任務
    // 若是添加任務時, 任務隊列已啓動, 直接將任務添加到任務隊列中,等待處理
    function queueTask(task) {
        if (!queue.length) {
            // 啓動任務隊列
            flushing = true
            // 等同步代碼執行完成之後, 處理任務隊列中的任務
            setTimeout(flushQueue, 0)
        }
        // 將任務添加到任務列中
        queue.push(task)
    }
    // 處理任務隊列中的任務
    function flushQueue() {
        // 遍歷任務隊列中的任務,處理每個任務
        while(index < queue.length) {
            queue[index].call()
            index++
        }
        // 處理完成之後,清空並關閉任務隊列
        queue = []
        index = 0
        flushing = false
    }
    
    複製代碼
  2. 構建 Promise 類

    要實現 Promise,首先須要提供一個 Promise 類。一個 Promise 類 須要 構造函數原型方法then、catch、finally靜態方法resolve、reject、all、race、any、allSetted

    其次,咱們還須要一些 輔助函數exectorresolverejecthandle。其中, resolvereject 用於修改 promise 對象狀態exector 用於 執行構造 promise 對象時傳入的 fnhandle 用於處理 thencatchfinally 方法註冊的 callback

    class MyPromise {
        // 構造函數
        constructor(fn) {}
        // 原型方法 - then
        then(onFullfilled, onRejected) {}
        // 原型方法 - catch
        catch(onRejected) {}
        // 原型方法 - finally
        finally(callback) {}
        // 靜態方法 - resolve
        static resolve(value) {}
        // 靜態方法 - reject
        static reject(reason) {}
        // 靜態方法 - all
        static all(arr) {}
        // 靜態方法 - race
        static race(arr) {}
        // 靜態方法 - any
        static any(arr) {}
        // 靜態方法 - allSetted
        static allSetted(arr) {}
    }
    // 輔助函數,用於執行構建 promise 對象傳入的 fn
    function exector(fn) {}
    // 輔助函數,將 promise 對象的狀態變爲resolved
    function resolve(promise, value) {}
    // 輔助函數,將 promise 對象的狀態變爲rejectd
    function reject(promise, value) {}
    // 輔助函數,用於處理 promise 對象 的 callback
    function handle(promise, handler)
    複製代碼
  3. 實現構造函數

    接下來,咱們首先來實現 構造函數 - constructor

    class MyPromise  {
        constructor(fn) {
            // promise 對象的初始狀態爲 'pending'
            this._status = 'pending'
            // promise 對象的初始值爲 'undefined'
            this._value = undefined
            // 用於緩存註冊的callback,當狀態發生變動時,會遍歷並處理
            this._handlers = []
            this._effects = []
            // then方法中會調用構造函數構建一個新的promise對象
            // 使用構造函數的時候,不傳入fn,也就不會執行fn
            if(!fn) return
            // 執行 fn
            exector(this, fn)
        }
    }
    
    複製代碼

    在構建 promise 對象 的時候,咱們會爲 promise 對象 添加以下屬性:_status_value_handlers_effects

    _statuspromise 對象狀態,初始值爲 'pending', 終態爲 'resolved''rejected'

    _valuepromise 對象 的值,初始值爲 undefined

    _handlers 用於緩存 promise 對象 經過 thencatchfinally 註冊的 callback。等 promise 對象狀態 發生變化時,遍歷 _handlers 中的 callback 並處理。

    _effects 中存儲的是 promise 對象。當咱們使用 resolve 方法修改 狀態 時,若是傳入的是一個 promise對象 - p1,那麼 p1 的狀態 會影響 原 promise 對象 - p2 的狀態。此時咱們會把 p2 添加到 p1_effects 中, 等到 p1 的狀態 發生變動時, 通知 p2 更新。

  4. 輔助函數 exector、resolve、reject、handle

    使用構造函數建立 promise 對象 時, 若是傳入了 fn, 須要經過輔助函數 exector 來執行 fnexector 的過程以下:

    function exector(promise, fn) {
        try {
            // 執行fn, 傳入 resolve 和 reject
            fn(value => {resolve(promise, value)},   // resolve
                reason => { reject(promise, reason)}) // reject
        } catch(e) {
            // 執行fn的過程當中,若是發生異常, 將promise對象的狀態置爲rejected
            reject(promise, e)
        }
    }
    複製代碼

    執行fn的時候, 咱們傳入 通過包裝的函數 做爲 resolvereject。當咱們拿到異步操做的結果後,將結果做爲參數傳入 resolvereject,將 promise 對象 的狀態變爲 resolvedrejected

    經過輔助函數 resolve, 咱們能夠將 promise對象 的狀態置爲 resolved

    function resolve(promise, value) {
        // 若是 promise對象的狀態已經爲終態, 直接返回
        if (promise._status !== 'pending') return
        if (value && typeof value === 'object') {
            // 使用resolve時,若是傳入的是一個promise對象,promise對象的狀態會傳遞給當前promise對象
            if (value instanceof MyPromise) {
                // 傳遞狀態
                promise._status = value._state
                // 傳遞值
                promise._value = value._value
                if (value._status !== 'pending') {
                    // 若是傳入的promise對象的狀態是resolved, 那麼當前promise對象的狀態會變爲resolved
                    // 此時須要將當前promise對象註冊的callback所有添加到微任務隊列中
                    promise._handlers.forEach(handler => {
                        handle(promise, handler)
                    })
                } else {
                    // 若是傳入的promise對象的狀態是 pending
                    // 須要將當前promise對象添加到傳入的promise對象的_effects列表中
                    // 等到傳入的promise對象的狀態發生變化時,通知當前promise對象進行狀態變化
                    value._effects.push(promise)
                }
                return
            } else if (value.then && typeof value.then === 'function') {
                // 若是傳入的是一個 thenable 對象
                exector(promise, value.then.bind(value))
                return 
            }
        }
        // 若是傳入的是普通值, 那麼將當前promise對象的狀態置爲resolved
        promise._status = 'resolved'
        // 傳入的值爲promise對象的值
        promise._value = value
        // 遍歷_handlers列表, then、catch、finally註冊的callback添加到微任務隊列中
        promise._handlers.forEach(handler => {
            handle(promise, handler)
        })
        // 通知_effects列表中的promise對象進行狀態變動
        promise._effects.forEach(item => {
            resolve(item, promise._value)
        })
    }
    複製代碼

    經過輔助函數 reject, 咱們能夠將 promise 對象 的狀態變爲 rejected

    function reject(promise, error) {
        // 若是promise對象的狀態爲終態, 直接返回
        if (promise._status !== 'pending') return
        // promise 對象 的狀態變爲 rejected
        promise._status = 'rejected'  
        // 傳入的值爲promise對象的值
        promise._value = error
        // 遍歷_handlers列表, then、catch、finally註冊的callback添加到微任務隊列中
        promise._handlers.forEach(handler => {
            handle(promise, handler)
        })
        // 通知_effects列表中的promise對象進行狀態變動
        promise._effects.forEach(item => {
            reject(item, promise._value)
        })
    }
    複製代碼

    經過輔助函數 handle, 咱們能夠將 promise對象 註冊的 callback 收集到 _handlers 列表 中。當 promise 對象 的狀態爲 終態 時, 將註冊的 callback 添加到 微任務隊列 中。

    // handler是一個對象,裏面包含promise對象註冊的onFullfilled、onRejected 和 執行 'then''catch''finally'方法時返回的 promise對象
    function handle(promise, handler) {
        // 若是 promise 實例的狀態爲pending, 將註冊的callback先收集起來。
        // 等promise對象的狀態變爲終態時,將callback添加到微任務隊列中
        if (promise._status === 'pending') {
            promise._handlers.push(handler)
            return
        }
        // promise實例的狀態爲resolved或者rejected時, 將註冊的callback添加到微任務隊列中, 等待執行
        queueTask(function() {
            // 微任務隊列啓動後, 開始處理微任務隊列中的任務
            // 若是promise 對象的狀態爲resolved, 獲取onFullfilled
            // 若是promise 對象的狀態爲rejected, 獲取onRejected
            let cb = promise._status === 'resolved' ? handler.onFullfilled : handler.onRejected;
            if (!cb) {
                // 若是callback沒有正確註冊
                // 'p2 = p1.then(onFullfilled, onRejected)'
                // 若是p1沒有正確註冊callback,即p1爲resolved,卻沒有註冊onFullfilled;
                // 或者 p1爲rejected,卻沒有註冊onRejected
                if (promise.status === 'resolved') {
                    // 若是p1的狀態爲resolved,將p2的狀態置爲resolved
                    // p2的值爲p1的值
                    resolve(handler.promise, promise._value)
                } else {
                    // 若是p1的狀態爲rejected,將p2的狀態置爲rejected
                    // p2的值爲p1的值
                    reject(handler.promise, promise._value)
                }
                return
            }
            // 若是callback有正確註冊
            try {
                // 執行callback
                let res = cb(promise._value)
                // 'p2 = p1.then()'
                // 將p2的狀態置爲resolved, 並使用callback的返回值做爲p2的值
                resolve(handler.promise, res)
            } catch (e) {
                // callback執行異常,將p2的狀態置爲rejected,將異常做爲p2的返回值
                reject(handler.promise, e)
            }
        })
    }
    複製代碼
  5. then

    promise對象 構建完成之後, 咱們須要經過 then 方法來註冊 onFullfilledonRejected。等到 promise 對象 的狀態變爲終態時,執行對應的 callback

    class Promise {
        then(onFullfilled, onRejected) {
            let P = this.constructor
            // promise.then 方法會返回一個 promise 實例
            let res = new P()
            // 若是當前promise對象的狀態爲pending,會將{onFullfilled, onRejected,..} 添加到_handlers中,等到狀態變爲終態, 再作處理
            // 若是當前promise對象的狀態爲終態, 會將callback添加到微任務隊列中
            handle(this, {
                onFullfilled,
                onRejected,
                promise: res
            })
            // 返回一個新的promise對象
            return res
        }
    }
    複製代碼
  6. catch

    catch 方法用於註冊當 promise 對象的狀態 變爲 rejected 時調用的 callback

    catch(onRejected) {
        this.then(null, onRejected)
    }
    複製代碼
  7. finally

    finally,用於 註冊promise 對象的狀態 變爲 終態(resolved/rejected) 時調用的 callback

    // 只要promise實例的狀態發生變化, 都會執行,返回一個promise實例
    // promise實例的值爲上一個promise實例的值
    finally(callback) {
        let P = this.constructor
        let res = new P()
        handle(this, {
            onFullfilled: () => {
                // 當原promise實例的狀態變爲resolved時,執行callback
                callback()
                // 返回原promise對象的值做爲新promise對象的值
                return this._value
            },
            onRejected: () => {
                // 當原promise實例的裝填變爲rejected, 執行callback
                callback()
                // 返回原promise對象的值做爲新promise對象的值
                return this._value
            },
            promise: res
        })
        // 返回一個新的promise對象
        return res
    
    }
    複製代碼
  8. Promise.resolve

    靜態方法 resolve, 用於快速構建一個 promise對象promise 對象的狀態 有傳入的參數決定。

    static resolve(value)  {
        // 傳入一個promise對象, 直接返回參數
        if (value instanceof MyPromise) return value
        // 傳入一個thenable對象,構建一個新的promise對象
        // thenable對象的狀態和值決定新的promise對象的狀態和值
        if (value && value.then && typeof value.then === 'function') {
            return new MyPromise(value.then.bind(value))
        }
        // 其餘類型的參數,直接返回狀態爲resolved的promise對象
        // promise對象的值爲傳入的參數
        let promise = new MyPromise()
        promise._status = 'resolved'
        promise._value = value
        return promise
    }
    複製代碼
  9. Promise.reject

    靜態方法 reject,用於快速構建一個狀態爲 rejectedpromise對象,傳入的參數爲 promise 對象 的值。

    static reject(value) {
        let promise = new MyPromise()
        promise._state = 'rejected'
        promise._value = value
        return promise
    }
    複製代碼
  10. Promise.all

    靜態方法 all 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的狀態都爲 resolved, 返回的 新的 promise 對象 的狀態變爲 resolved, 不然爲 rejected

    static all(arr) {
        var args = Array.prototype.slice.call(arr)
        // all 方法會返回一個新的promise對象
        return new MyPromise(function(resolve, reject) {
            if (args.length === 0) return resolve([])
            let remain = args.length
            // 若是promise對象的狀態爲resolved, 把promise對象的值先緩存起來
            // 若是promise對象的狀態爲pending,等promise的狀態變爲resolved,把promise對象的狀態緩存起來
            // 當全部的promise對象的狀態爲resolved時,將新的promise對象的狀態置爲resolved, 使用緩存的數組做爲新的promise對象的值
            // 若是promise對象的狀態爲rejected,直接將新的promise對象的狀態置爲rejected
            function func(index, val) {
                if (typeof val === 'object') {
                    if (val instanceof MyPromise) {
                        // promise對象的狀態爲resolved, 緩存promise對象的值
                        if (val._status === 'resolved') return func(index, val._value)
                        // promise對象的狀態爲rejected,新的promise對象的狀態爲rejected
                        if (val._status === 'rejected') {
                            // 新的promise對象的值爲第一個狀態爲rejected的promise對象的值
                            reject(val._value)
                            return false
                        }
                        // promise對象的狀態爲pending
                        val.then(value => {
                            func(index, value)
                        }, reject)
                        return true
                    } else if (val.then && typeof val.then === 'function') {
                        // 傳入的參數是thenable對象
                        let p = new MyPromise(val.then.bind(val))
                        p.then(value => {
                            func(index, value)
                        }, reject)
                        return true
                    }
                }
                // 若是promise對象的狀態爲resolved, 緩存promise對象的值
                args[index] = val
                // 傳入的promise對象的狀態都變爲resolved, 返回的promise對象的狀態變爲resolved
                // 值爲一個數組,包含全部promise對象值
                if (--remain === 0) {
                    resolve(args)
                }
                return true
            }
            // 遍歷傳入的promise對象
            for(let i = 0; i < args.length; i++) {
                if (!func(i, args[i])) return false
            }
        })
    }
    複製代碼
  11. Promise.race

    靜態方法 race 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的狀態只要有一個是 終態 時, 返回的 新的 promise 對象 的狀態變爲 相應的狀態

    static race(arr) {
        // 返回一個promise對象
        return new MyPromise(function(resolve, reject) {
            arr.forEach(function(value){
                //  arr 中只要有一個 promise 實例的狀態爲發生變化, 返回的 promise的狀態就會發生變化
                // 返回的promise對象的值爲參數中第一個狀態變化的promise對象的值
                MyPromise.resolve(value).then(resolve, reject);
            });
        })
    }
    複製代碼
  12. Promise.allSettled

    靜態方法 allSettled 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的狀態都變爲 終態 時, 返回的 新的 promise 對象 的狀態變爲 resolved

    static allSettled(arr) {
        var args = Array.prototype.slice.call(arr)
        // 返回一個新的promise對象
        return new MyPromise(function(resolve, reject) {
            if (args.length === 0) return resolve([])
            let remain = args.length
            function func(index, val) {
                if (typeof val === 'object') {
                    // 參數爲promise對象
                    if (val instanceof MyPromise) {
                        // promise對象的狀態爲resolved, 緩存promise對象的值
                        if (val._status === 'resolved') return func(index, val._value)
                        // promise對象的狀態爲rejected, 緩存promise對象的值
                        if (val._status === 'rejected') return func(index, val._value)
                        // promise對象的狀態爲pending, 等promise對象的狀態變爲終態時,緩存promise對象的值
                        val.then((value) => {
                            func(index, value)
                        }, (error) => {
                            func(index, error)
                        })
                    } else if (val.then && typeof val.then === 'function') {
                        // 參數爲thenable對象
                        let p = new MyPromise(val.then.bind(val))
                        p.then((value) => {
                            func(index, value)
                        }, (error) => {
                            func(index, error)
                        })
                    }
                }
                // 參數爲普通值,直接緩存
                args[index] = val
                if (--remain === 0) {
                    // 全部的promise對象的狀態都爲終態,將返回的promise對象的狀態變爲resolved
                    // 值爲全部promise對象的值
                    resolve(args)
                }
            }
            // 遍歷傳入的全部promise對象
            for(let i = 0; i < args.length; i++) {
                func(i, args[i])
            }
        })
    }
    複製代碼
  13. Promise.any

    靜態方法 any 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的只要有一個狀態爲 resolved, 返回的 新的 promise 對象 的狀態變爲 resolved。 只有 全部 promise 對象 的狀態都爲 rejected, 返回的 新的 promise 對象 的狀態才爲 rejected

    static any(arr) {
        var args = Array.prototype.slice.call(arr)
        // 返回一個新的promise對象
        return new MyPromise(function(resolve, reject) {
            if (args.length === 0) return resolve([])
            let remain = args.length
            function func(index, val) {
                if (typeof val === 'object') {
                    // 傳入的參數爲promise對象
                    if (val instanceof MyPromise) {
                        // promise對象的狀態爲resoved, 則返回的promise對象的狀態爲resolved
                        // 值爲第一個狀態爲resolved的promise對象的值
                        if (val._status === 'resolved') {
                            resolve(val._value)
                            return false
                        }
                        // promise對象的狀態爲rejected, 緩存promise對象的值
                        if (val._status === 'rejected') return func(index, val._value)
                        // promise對象的狀態爲pending, 等promise對象的狀態變爲rejected是,緩存promise對象的值;
                        // 變爲resolved時, 返回的promise對象的狀態變爲resolved
                        val.then(resolve, (error) => {
                            func(index, error)
                        })
                        return true
                    } else if (val.then && typeof val.then === 'function') {
                        // 傳入的參數是thenable對象
                        let p = new MyPromise(val.then.bind(val))
                        p.then(resolve, (error) => {
                            func(index, error)
                        })
                        return true
                    }
                }
                // 傳入的參數是普通值
                args[index] = val
                // 全部的promise對象的狀態都爲rejected
                if (--remain === 0) {
                    // 將返回的promise對象的狀態變爲rejected
                    // 返回的promise對象的值爲傳入的全部promise對象的值
                    reject(args)
                }
                return true
            }
            // 遍歷傳入的promise對象
            for(let i = 0; i < args.length; i++) {
                if (!func(i, args[i])) return false
            }
        })
    } 
    複製代碼
相關文章
相關標籤/搜索