Dealing with Arrays of Deferred Objects

前端 未结 3 882
情书的邮戳
情书的邮戳 2021-02-09 02:56

Since using $.Deferred I\'ve run into this scenario a couple times: I have a list of values each of which yields a Deferred Object in some way and I want to execute

相关标签:
3条回答
  • 2021-02-09 02:56

    Yes there is, you should never reference a lookup value in a loop. Always make a copy.

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

    But seriously, I'm just joshin' you. That code rocks. Stick with it.

    0 讨论(0)
  • 2021-02-09 02:56

    Here is a helper function I wrote called LoadInitialData, it can be called like this 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);
    
    0 讨论(0)
  • 2021-02-09 03:13

    A more elegant way to write this example is with the array map function (or jQuery's $.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
    });
    

    You could even roll your own "whenDone" and "fetchURL" functions:

    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 讨论(0)
提交回复
热议问题