8
votes

Traiter avec des tableaux d'objets différés

depuis l'utilisation $. Referedred J'ai rencontré ce scénario plusieurs fois: j'ai une liste de valeurs chacune d'un objet différé d'une manière ou d'une autre et je veux exécuter un rappel une fois Tous les objets différés sont résolus.

Un exemple plus concret serait quelque chose comme ceci: xxx

existe une solution plus élégante que le code dans mon exemple? < / p>


2 commentaires

Pourquoi pensez-vous que ce n'est pas élégant?


Après avoir écrit un code comme celui-ci pour la 3ème fois, j'ai commencé à penser que c'est un scénario assez commun et pourrait être géré par le cadre d'objets différés de manière meilleure que je négligeais simplement.


3 Réponses :


3
votes

Oui, vous ne devez jamais faire référence à une valeur de recherche dans une boucle. Toujours faire une copie.

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 commentaires

Vous êtes correct sur la valeur de la recherche mais l'avoir dans la déclaration (i.e. var i = 0, j = urls.length ) le cache. Ce que vous voulez éviter, c'est l'avoir dans la comparaison (c'est-à-dire i ). :-)



0
votes

Voici une fonction d'assistance que j'ai écrite appelée loadinitialdata, elle peut être appelée comme ceci loadinitialdata (URLARRAY, DATARETURNEDARRAY, rappel) code>

    ///  
///  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 commentaires

3
votes

Un moyen plus élégant d'écrire cet exemple est avec la fonction mappée Array (ou JQuery's $ .map):

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 commentaires