201207091420jQuery Deferred Object

jQuery Deferred 物件是依 CommonJS Promises/A 實作。但在 jQuery 1.8 版才依 Promises/A 將 deferred.then() 實作為與 deferred.pipe() 一模一樣,並且將 deferred.pipe() 列入 deprecated 。

我覺得 jQuery Deferred 物件難懂,一大問題在於官方範例沒有將 Deferred 物件 chain 起來,以 deferred.then() 中的 Chain tasks 範例為例:

var request = $.ajax( url, { dataType: "json" } ),
    chained = request.then(function( data ) {
      return $.ajax( url2, { data: { user: data.userId } } );
    });
 
chained.done(function( data ) {
  // data retrieved from url2 as provided by the first request
});

本意是先發出 ajax 到 url ,待取得 ajax url 的結果再發出 ajax 到 url2 ,取得 ajax url2 的結果再執行 .done 。稍作整理,將變數 request 與 chained 拿掉:

$.ajax( url, { dataType: "json" } )
    .then(function( data ) {
        return $.ajax( url2, { data: { user: data.userId } } );
    })
    .done(function( data ) {
        // data retrieved from url2 as provided by the first request
    });

應該容易理解多了。

再以 .promise() 範例 Resolve the returned Promise when all animations have ended 其中的這段為例:

$("div").each(function( i ) {
  $( this ).fadeIn().fadeOut( 1000 * (i+1) );
});

$("div").promise().done(function() {
  $( "p" ).append( " Finished! " );
});

稍作整理,將兩個 $("div") 合併:

$("div")
    .each(function( i ) {
      $( this ).fadeIn().fadeOut( 1000 * (i+1) );
    })
    .promise()
    .done(function() {
      $( "p" ).append( " Finished! " );
    });

再搭配「 .fadeIn().fadeOut()Effects 相關 method 會產生 Deferred 物件藉由 .data() 綁定到 jQuery 物件上」與「對 jQuery 物件執行 .promise() 會藉由 .data() 尋找綁在 jQuery 物件上 Deferred 物件」的認知,應該也會容易理解的多。

jQuery Deferred 物件討厭的地方在於,企圖使用 $.when 做兩件事,當僅傳入一個參數時,做的事是「將非 Deferred 物件變數包覆為 Deferred 物件」:

$.when( { testing: 123 } )
    .done(function(x) {
        alert(x.testing); /* alerts "123" */
    });

當傳入多個參數時,做的事是「將多個 Deferred 物件整併為一個 Deferred 物件」:

$.when($.ajax("/page1.php"), $.ajax("/page2.php"))
    .done(function(a1,  a2){
        /* a1 and a2 are arguments resolved for the
           page1 and page2 ajax requests, respectively */

        var jqXHR = a1[2];
        
        /* arguments are [ "success", statusText, jqXHR ] */
    
        if ( /Whip It/.test(jqXHR.responseText) ) {
          alert("First page has 'Whip It' somewhere.");
        }
    });

也就是傳入一個參數與傳入多個參數時,介面並不一致。當我們試圖以 apply 搭配陣列傳遞參數進入 $.when 時,需特別注意陣列的長度是否可能為 1 :

$.when.apply($, arr);

最後 jQuery 在 Deferred 物件中又切出 Promise 物件,單看說明文件,有點難懂兩者的差異。直接看程式碼容易的多,在程式碼中找「 Deferred: 」和「 promise: 」,可以看到 jQuery 在 Deferred 物件中產生一擁有 Deferred 物件 method 的 Promise 物件,並利用 Closure 使 Promise 物件動不到 Deferred 物件的 state

回應
Google 站內搜尋
BloggerAds
累積 | 今日
loading......
    沒有新回應!





Powered by Xuite