2013-02-22 48 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