8

的阵列处理由于使用$.Deferred我碰到的这种情况下几次:我有值的列表,每个的产生以某种方式Deferred对象,我想执行一次回调所有的延迟对象已解析。与递延对象

更具体的例子是这样的:

var urls = [ 'foo.com', 'bar.com', 'baz.com', 'qux.com' ], 
    defers = [], defer; 

for(var i = 0, j = urls.length; i < j; i++){ 
    defer = $.ajax({ 
     url: 'http://' + urls[ i ] 
    }); 

    defers.push(defer); 
} 

$.when.apply(window, defers).done(function(){ 
    // Do Something 
}); 

是否有一个更优雅的解决方案比我的示例代码?

+2

你为什么认为,这不是优雅的? – topek

+0

在第三次编写这样的代码之后,我开始认为这是一个相当常见的场景,并且可以通过延迟对象框架以更好的方式处理,而我可以忽略它。 –

回答

3

是有,你不应该在一个循环引用查找值。一定要复印。

var urls = [ 'foo.com', 'bar.com', 'baz.com', 'qux.com' ], 
    defers = [], defer; 

var urlsLength = urls.length; 
for(var i = 0, j = urlsLength; i < j; i++){ 
    defer = $.ajax({ 
     url: 'http://' + urls[ i ] 
    }); 

    defers.push(defer); 
} 

$.when.apply(window, defers).done(function(){ 
    // Do Something 
}); 

但严重的是,我只是joshin'你。该代码岩石。坚持下去。

+1

您即将查找值正确的,但在声明具有它(即'变种I = 0,J = urls.length')缓存它。要避免什么是有它的比较(即'I'urls.length')。 :-) –

0

这里是一个辅助功能,我编写的名为LoadInitialData,可以这样调用LoadInitialData(urlArray, dataReturnedArray, callback)

/// 
/// 1. The magical function LoadInitialData 
/// 

      /// 
      /// <summary> 
      /// This functions allows you to fire off a bunch of ajax GET requests and run a callback function when 
      /// all the requests come back that contains an array of all your ajax success data 
      /// </summary> 
      /// <params> 
      ///   urlArray - an array of urls to be looped and ajaxed 
      /// dataReturnedArray - this array will contain all data returned from your ajax calls. Its stuctured like this 
      ///   [{url: "http//site.com/1", "data": "your data"}, {url: "http//site.com/2", "data": "your data"}] 
      ///   dataReturnedArray[0] is data from call 1, dataReturnedArray[1] is data from call 2 etc. It might be a 
      ///   good idea to pass in a global array so you can use this data throughout your application. 
      ///  callback - a function that runs after all ajax calles are done, dataReturnedArray is available in the callback 
      /// </parms> 
      /// 
      function LoadInitialData(urlArray, dataReturnedArray, callback){ 
       // set up a deffered promise to fire when all our async calls come back 
       var urls = urlArray, defers = [], defer; 
        var urlsLength = urls.length; 
        for(var i = 0, j = urlsLength; i < j; i++){ 
         var u = urls[ i ]; 
          defer = $.ajax({ 
          type : "GET", 
          dataType : "jsonp", 
          url: u, 
          success: function(data){ 
           dataReturnedArray.push({ 
             url: u, 
             data: data 
           }); 
          } 
         }); 
         defers.push(defer); 
        } 
        $.when.apply(window, defers).then(function(){ 
          // Do Something now that we have all the data 
         console.log("done fetching all data"); 
         callback(dataReturnedArray); 
        }); 
      } 



/// 
/// 2. Your config…. urlArray, dataReturnedArray, callback 
/// 

     var app = app || {}; 
     app.data = []; // will hold the fetched data 
     var urlArr = ["http://site.com/2", "http://site.com/2"]; // the urls to get data from 


     // function to call once all the data is loaded 
     callback = function(data){ 

      // data cleansing 
      var tblData = [];       
      $.each(data, function(key, value){ 
        $.each(value.data, function(key, value){ 
          tblData.push(value); 
        }); 
      }); 

      $("#loader").hide(); 
     }; 


/// 
/// 3. Kick it all off! 
/// 

     // show a loader here 
     $("#loader").show(); 

     // fire off the code to fetch the initial data 
     LoadInitialData(urlArr, app.data, callback); 
3

更优雅的方式来写这个例子是与阵列地图功能(或jQuery的$ .MAP):

var urls = [ 'foo.com', 'bar.com', 'baz.com', 'qux.com' ]; 

var defers = urls.map(function(url) { 
    return $.ajax({ 
     url: 'http://' + url 
    }); 
}); 

$.when.apply(window, defers).done(function(){ 
    // Do Something 
}); 

你甚至可以推出自己的 “whenDone” 和 “fetchURL” 功能:

Array.prototype.whenDone = function(callback){ 
    return $.when.apply(window, this).done(callback); 
} 

function fetchURL(url){ 
    return $.ajax({ 
     url: 'http://' + url 
    }); 
} 

var urls = [ 'foo.com', 'bar.com', 'baz.com', 'qux.com' ];  

urls.map(fetchUrl).whenDone(function(){ 
    // Do Something 
}); 
+0

我喜欢使用Array.prototype.map'的'。这是更清洁。 –