Promise鏈式調用解析

Promise鏈式調用解析

關於Promise是作什麼的我就不贅述了,當你看到這個文章的時候,我也就默認你是用過Promise的數組

首先,舉個例子異步

// 獲取用戶id
function getUserId() {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        resolve(186)
      }, 1e3)
    })
}
// 經過用戶id獲取該用戶的手機號
function getMobileByUserId(userId) {
    return new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve(userId + '****5836')
        }, 1e3)
    })
}

兩個方法,getUserId(簡稱 IDfun )和getMobileByUserId(簡稱 MOfun ),二者都是return了一個Promise實例,前者是獲取用戶id,後者是拿着用戶id去換取手機號,MOfun的輸出是依賴於IDfun的輸出,這樣兩個異步的操做又得保證其是有序的執行函數

到這,應該都有一個對應的解決辦法,我這裏列舉了一個示例:this

IDfun()
    .then(MOfun)
    .then(function(res) {
        console.log(res)
    })

首先,調用了IDfun,在其Promise實例的then方法中傳入MOfun,緊隨其後又是一個then方法,裏面傳入了一個callback函數,此時,callback函數中打印的值是什麼,又是爲何呢,通常狀況下then方法裏傳的都是一個callback,而這個例子裏傳的倒是一個包含Promise的函數,它內部是怎麼作到將用戶的id傳遞給MOfun中並打印出來code

說到這,我先列舉幾個Promise中幾個比較核心的方法:對象

// this指向是Promise實例
// 只列舉了幾個關鍵的代碼
this.then = function (onFulfilled) {
    return new Promise(function (resolve) {
        handle({
            onFulfilled: onFulfilled || null,
            resolve: resolve
        });
    });
};

function handle(deferred) {
    if (state === 'pending') {
        deferreds.push(deferred);
        return;
    }

    var ret = deferred.onFulfilled(value);
    deferred.resolve(ret);
}
// 其中的state和value能夠理解爲全局定義的,只是放了一些代碼段出來
function resolve(newValue) {
    if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
        var then = newValue.then;
        if (typeof then === 'function') {
            then.call(newValue, resolve);
            return;
        }
    }
    state = 'fulfilled';
    value = newValue;     // value這裏能夠理解爲它是在全局定義的
    setTimeout(function () {
        deferreds.forEach(function (deferred) {
            handle(deferred);
        });
    }, 0);
}

參照這幾個方法,咱們再回到剛纔那個例子:隊列

  • 1.執行IDfun返回一個Promise實例( IDPro ),執行IDPro中的代碼,假設此時在異步發送請求,繼續執行then方法,then方法中傳入了MOfun
  • 2.進入到then方法中,也是返回一個Promise實例( BridgePro1 ),調用handle方法get

    handle({io

    onFulfilled: onFulfilled || null,  // 此時的onFulfilled === MOfun
    resolve: resolve  // resolve是BridgePro1的resolve

    });console

  • 3.進入handle中,若是是IDPro的then方法先執行,其resolve後執行,這個時候 state === pending,此時它會將傳入的對象push到IDPro的deferreds數組中,而後返回
  • 4.IDPro中異步操做完成,執行其resolve,並傳入id爲186
  • 5.進入resolve方法中,此時newValue不知足if條件,跳過,繼續向下執行,改變state===> fulfilled,value ===> 186,setTimeout爲0是爲了把其內部的這段代碼放到隊列的最後,保證執行這段代碼的時候then方法已經執行了,循環遍歷IDPro的deferreds數組,將數組中的每一項傳入handle中並執行
function resolve(newValue) {   // newValue === 186
        if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
            var then = newValue.then;
            if (typeof then === 'function') {
                then.call(newValue, resolve);
                return;
            }
        }
        state = 'fulfilled';
        value = newValue;     // value這裏能夠理解爲它是在全局定義的
        setTimeout(function () {
            // deferreds裏存放的是經過then傳入的
            // [{
            //    onFulfilled: MOfun,
            //    resolve: resolve
            // }]
            deferreds.forEach(function (deferred) {  
                handle(deferred);
            });
        }, 0);
    }
  • 6.進入handle中,此時state === fulfilled,執行deferred中的onFulfilled(MOfun),傳入value,返回一個Promise實例(MOPro),此時的ret === MOPro,繼續執行deferred中的resolve(BridgePro1的resolve),傳入ret
// state === fulfilled
    // deferred ===> 
    //  {
    //    onFulfilled: MOfun,
    //    resolve: resolve
    //  }
    function handle(deferred) {
        if (state === 'pending') {
            deferreds.push(deferred);
            return;
        }
    
        var ret = deferred.onFulfilled(value);  // value === 186
        deferred.resolve(ret);
    }
  • 7.進入resolve中,此時newValue知足判斷條件
function resolve(newValue) {   // newValue === MOPro
        if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
            // then 是MOPro的then
            var then = newValue.then;
            if (typeof then === 'function') {
                // 調用then方法,設置其內部this指向爲MOPro,並傳入resolve,這個resolve爲BridgePro1的resolve,而後返回
                then.call(newValue, resolve);
                return;
            }
        }
        state = 'fulfilled';
        value = newValue;     
        setTimeout(function () {
            deferreds.forEach(function (deferred) {  
                handle(deferred);
            });
        }, 0);
    }
  • 8.進入到MOPro的then方法中,調用handle將對象傳入,此時MOPro的deferreds數組中有兩項,一項是上面經過resolve傳入的,另外一項是傳入的callback函數
// ===> callback
    function(res) {
        console.log(res)
    }

    this.then = function (onFulfilled) {
        // onFulfilled爲BridgePro1的resolve 
        // 此時返回的Promise實例爲BridgePro2
        return new Promise(function (resolve) {
            handle({
                onFulfilled: onFulfilled || null,
                resolve: resolve  // BridgePro2
            });
        });
    };
  • 9.當MOPro中異步操做執行完成,執行resolve並傳入手機號1865836,進入resolve,將state設置爲fulfilled,value設置成1865836,延遲循環MOPro的deferreds數組,此時數組爲:
[
        {
            onFulfilled: resolve,   // BridgePro1的resolve
            resolve: resolve  // BridgePro2的resolve
        },
        {
             onFulfilled: callback,
            resolve: resolve  // BridgePro3的resolve
        }
    ]
  • 10.進入handle方法中,循環第一個值時,此時deferred的onFulfilled爲BridgePro1的resolve,調用該resolve,並傳入value(1865836),由於BridgePro1的deferreds爲空,因此直接resolve掉BridgePro1,此時ret爲undefined,再執行deferred的resolve(BridgePro2的resolve),一樣,resolve掉BridgePro2,繼續循環,傳入第二個值,deferred的onFulfilled爲callback,執行callback傳入value,打印出手機號1865836,返回值爲undefined ,所以ret爲undefined,再執行deferred的resolve(BridgePro3的resolve),直接resolve掉BridgePro3
function handle(deferred) {
        if (state === 'pending') {
            deferreds.push(deferred);
            return;
        }
    
        var ret = deferred.onFulfilled(value);
        deferred.resolve(ret);
    }
  • 11.至此,執行完成,經過user的id換取了user的mobile number

後記:

若是我想按照下面的寫法一直then下去:

IDfun()
    .then(MOfun)
    .then(callback)
    .then(callback)
    .then(callback)

每一個callback裏均可以打印到手機號,應該怎麼寫

// callback
function callback(res) {
    // doing something
    console.log(res)
    return res
}

總結:

Promise是什麼,從字面意思就是一個承諾,我給你了一個承諾,你記着呢,不知道何時兌現,但確定會給你一個答覆,打一個不太形象的比喻,我去銀行辦事,確定是先取一個號,這個號就像一個承諾,何時叫到你,不肯定,但確定會叫你,而後這個時候你就會去辦理你的事情,綜上,即爲Promise鏈式的原理解析,出錯的地方歡迎指出

相關文章
相關標籤/搜索