2013-02-22 50 views
12

我有三個函數,我試圖運行,前兩個正在做一些異步的東西,需要第三個使用的數據。我希望第三個函數僅在1和2都完成時觸發。這是一般結構,但最終的功能是在1和2完成之前發射。jquery自定義遞延函數

function run() { 
    var data1 = {}; 
    var data2 = {}; 

    $.when(first(), second()).done(constructData()); 

    function first() { 
     var d = new $.Deferred(); 

     //do a bunch of stuff async 
     data1 = {}; 

     d.resolve(); 
    } 
    function second() { 


     var d = new $.Deferred(); 

     //do a bunch of stuff async 
     data2 = {}; 
     d.resolve(); 
    } 
    function constructData() { 
     //do stuff with data1 and data2 
    } 

} 

答案是不調用構造數據立即

$.when(first(), second()).done(constructData); 

回答

23

您應該返回承諾對象。您也有一個錯誤在這行:

$.when(first(), second()).done(constructData()); 

應該

$.when(first(), second()).done(constructData); // don't call constructData immediately 

所以一起則可能是:

function run() { 
    var data1 = {}; 
    var data2 = {}; 

    $.when(first(), second()).done(constructData); 

    function first() { 
     return $.Deferred(function() { // <-- see returning Deferred object 
      var self = this; 

      setTimeout(function() { // <-- example of some async operation 
       data1 = {func: 'first', data: true}; 
       self.resolve();  // <-- call resolve method once async is done 
      }, 2000); 
     }); 
    } 
    function second() { 
     return $.Deferred(function() { 
      var self = this; 
      setTimeout(function() { 
       data2 = {func: 'second', data: true}; 
       self.resolve(); 
      }, 3000); 
     }); 
    } 
    function constructData() { 
     //do stuff with data1 and data2 
     console.log(data1, data2); 
    } 
} 

http://jsfiddle.net/FwXZC/

+0

不立即調用構造數據的伎倆感謝! – Brian 2013-02-22 08:14:55

+0

哇,不知道這個函數可以寫在延期對象裏面,謝謝! – Denis 2013-10-04 14:00:15

+0

@Denis我不認爲這是正確的做法。根據jQuery [docs](https://api.jquery.com/jquery.deferred/):'beforeStart'參數是_「一個在構造函數返回之前調用的函數。」_。因此,在創建延遲對象之前調用該函數。 – 2016-12-30 11:56:05

1

我想你應該有first()second()返回一個承諾:return d.promise();。從docs

如果一個參數傳遞給jQuery.when,這是不是一個延期或承諾,爲解決延遲和連接任何doneCallbacks將立即執行將被處理。

我懷疑這可能是爲什麼when呼叫太快呼叫constructData

很難從代碼中告知代碼,但請確保在異步操作完成後調用d.resolve()

您可能會發現顯式設置data1data2的更自然的方法是使用調用resolve時提供的數據。這將意味着你的when調用看起來是這樣的:

$.when(first(), second()).done(function(result1, result2) { 
    data1 = result1[0]; 
    data2 = result2[0]; 

    constructData(); 
}); 

注意,提供給done方法結果的準確格式取決於延遲的對象的性質。如果承諾是從致電$.ajax返回的,則結果應該是[data, statusText, jqXhrObject]

+0

是的,我沒加所有的異步代碼它都是一堆自定義非jquery ajax請求,錯誤是我如何調用done函數 – Brian 2013-02-22 08:16:58