jQuery-v2.0.3源碼淺析05-when

jQuery提供的when方法可以管理多個Deferred對象。打比方說如果你創(chuàng)建了多個Deferred對象,這個時候你想等所有Deferred調(diào)用完畢之后執(zhí)行一段代碼,這個時候我們就可以使用when來實(shí)現(xiàn)。

源碼

/**源碼3089行**/
when: function( subordinate /* , ..., subordinateN */ ) {
    var i = 0,
        resolveValues = core_slice.call( arguments ),
        length = resolveValues.length,

        /**源碼3095行**/
        remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,

        /**源碼3098行**/
        deferred = remaining === 1 ? subordinate : jQuery.Deferred(),

        // Update function for both resolve and progress values
        updateFunc = function( i, contexts, values ) {
            return function( value ) {
                contexts[ i ] = this;
                values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
                if( values === progressValues ) {
                    deferred.notifyWith( contexts, values );
                } else if ( !( --remaining ) ) {
                    deferred.resolveWith( contexts, values );
                }
            };
        },

        progressValues, progressContexts, resolveContexts;

    /**源碼3116行**/
    if ( length > 1 ) {
        progressValues = new Array( length );
        progressContexts = new Array( length );
        resolveContexts = new Array( length );
        for ( ; i < length; i++ ) {
            if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
                resolveValues[ i ].promise()
                    .done( updateFunc( i, resolveContexts, resolveValues ) )
                    .fail( deferred.reject )
                    .progress( updateFunc( i, progressContexts, progressValues ) );
            } else {
                --remaining;
            }
        }
    }

    /**源碼3133行**/
    if ( !remaining ) {
        deferred.resolveWith( resolveContexts, resolveValues );
    }

    return deferred.promise();
}

原理

when的原理:
利用remaining來記錄Deferred的數(shù)量,如果傳入的不是Deferred對象,則不記錄(源碼中直接進(jìn)行remaining-1操作)。當(dāng)Deferred執(zhí)行成功之后會將remaining進(jìn)行-1操作,當(dāng)最后一個Deferred執(zhí)行完畢(成功)之后(remaining等于0的時候)這個時候我們就會觸發(fā)when方法里面創(chuàng)建的Deferred對象。如果遇到其中一個Deferred調(diào)用了失敗方法,則直接調(diào)用when的reject。如果傳入的參數(shù)沒有一個是Deferred對象,則直接調(diào)用回調(diào)函數(shù)。

解釋

首先來看源碼3095行和源碼3098行,這里的意思是值如果傳入的參數(shù)如果只有一個并且是Deferred對象,則直接使用這個Deferred對象,如果傳入的這個參數(shù)不是Deferred對象或者存在多個參數(shù)則直接創(chuàng)建一個新的Deferred對象。

源碼3116行判斷如果參數(shù)個數(shù)大于1個的時候,這個時候我們首先來循環(huán)這些參數(shù)判斷是否是Deferred對象,如果不是則將remaining直接進(jìn)行-1操作,如果是Deferred對象,這個時候我們可以看到done和progress都調(diào)用了updateFunc函數(shù)。在updateFunc函數(shù)里面進(jìn)行了判斷如果第三個參數(shù)是progressValues則直接調(diào)用我們創(chuàng)建的deferred的notifyWith,所以綁定在when后面的progress可能會觸發(fā)多次根據(jù)參數(shù)中Deferred對象調(diào)用progress的次數(shù)而定。如果是done觸發(fā)的
updateFunc方法,這個時候我們會先將remaining進(jìn)行-1操作,如果remaining等于0的時候則直接觸發(fā)deferred的resolveWith。

源碼3133行的意思就是 如果我們傳入的參數(shù)全都不是Deferred對象,這個時候我們就直接觸發(fā)成功的方法。最后return deferred.promise();不給外部提供修改狀態(tài)的方法。

用法

var def1 = $.Deferred();
setTimeout(function(){
    def1.resolve();
}, 1000);

$.when(def1).done(function(){
    console.log('全部成功');
}).fail(function(){
    console.log('有失敗');
})
//1秒中之后會調(diào)用成功
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、什么是deferred對象? 開發(fā)網(wǎng)站的過程中,我們經(jīng)常遇到某些耗時很長的javascript操作。其中,既有...
    壯哉我大前端閱讀 308評論 0 1
  • jQuery的deferred對象詳解 作者:阮一峰 一、什么是deferred對象? 開發(fā)網(wǎng)站的過程中,我們經(jīng)常...
    JamHsiao_aaa4閱讀 359評論 0 0
  • 不亂于心,不困于情 不畏將來,不念過往,如此,安好!
    澹然四海清閱讀 292評論 0 0
  • 晚上下了實(shí)驗(yàn)課,和阿飛去吃瓦罐,香菇排骨。飛就著湯和小菜很快吃完一盅米,又打了一份回來和我分著吃。瓦罐口小肚大,拿...
    韓劇里的男二號閱讀 499評論 5 1
  • 我感覺好久沒下雨了 今天的雨也不在我的預(yù)料中 就好像你每一次悄無聲息推開我的門 我似乎只有在下雨的時候才想起你 你...
    云淡風(fēng)輕之藍(lán)閱讀 475評論 20 35

友情鏈接更多精彩內(nèi)容