8

使用して以来$.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回目に書いた後、私はそれがかなり一般的なシナリオだと思ってしまい、Deferred Objectsフレームワークがより簡単な方法で処理できるかもしれないと思っています。 –

答えて

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 
}); 

しかし、真剣に、私はちょうどあなたを尊敬しています。そのコードは揺れる。それにこだわります。 :ここでは

+1

ルックアップの値は正しいですが、宣言で(var i = 0、j = urls.length'など)それをキャッシュしています。あなたが避けたいのは、それを比較(つまり、 'i

0

がLoadInitialDataと呼ばれる私が書いたヘルパー関数です、この例を記述するために、よりエレガントな方法は、配列のマップ機能(またはjQueryの$ .MAP)であり、この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

のように呼び出すことができます

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'の使い方が好きです。それはより清潔です。 –

関連する問題