开发者

Perform many AJAX requests in parallel, and run a function after all of them complete

开发者 https://www.devze.com 2023-02-28 16:43 出处:网络
I\'m trying to accomplish the following sequence of operations using JQuery in HTML. A list of urls is constructed

I'm trying to accomplish the following sequence of operations using JQuery in HTML.

  • A list of urls is constructed
  • Each of these urls is requested using $.getJSON(url) in parallel
  • Wait for all requests to complete or to fail (404 might happen)
  • Take the data of all completed JSON-Requests and do something.

I constructed the Java-Script code posted below. It works perfecly except if one of the requests fails due to a 404-error: Then, $.when does not run because it instantly aborts if a requests fails. Can you somehow override the ajax-requests, so they don't fail but instead return a empty source?

I already read this and this post, but it does not provide a solution where code can be run after all queries have completed.

function fetchData() {
    queries = [];
    //urls is initialized somewhere else containing all urls
    for(var url in urls) {
        queries.pu开发者_Go百科sh($.getJSON(url));
    }

    $.when.apply(this, queries).done(function() {
        console.log("Finished all queries, got "+arguments.length+" results");
        //Now arguments is a array containing the results of all requests
    }

    //function returns instantly, no problem!
 }


I might do something like this:

$(document).ready(function(){
    var _q = ['/echo/json/', '/echo/json/', 'mybadurl'];
    var _d = [];
    for(u in _q)
    {
        $.ajax({
            url: _q[u],
            success: function(data){
                pushData(data);
            },
            error: function(x){
                pushData(x);
            }
        });
    }

    function pushData(d)
    {
        _d.push(d);
        if(_d.length == _q.length)
        {
            alert('were done');
        }
    }
});

Here, you're pushing data from either the success or error onto the array _d and testing to make sure you've received all replies before continuing (alert('were done');).

Of course, you could make this smarter by pushing an object that contains op state along with the payload into _d, but this was a quick hack together to demonstrate how I'd most likely go about doing what you're asking.

Fiddle here


Something like this:

function fetchData() {
    queries = [];
    //urls is initialized somewhere else containing all urls
    for(var url in urls) {
        queries.push($.getJSON(url));
    }

    var returned = 0;
    for (var i = 0; i < queries.length; i += 1) {
        call_ajax_somehow(queries[i], function () {
            console.log("callback called");
            returned += 1;
            if (returned === queries.length) {
                console.log("Got all " + queries.length + " of them");
            }
        });
    }
 }

You'd have to check the jQuery ajax spec on how to call it exactly and how to handle the errors (ie, how to specify the error callback) but it shouldn't be too hard to modify the code.


Something like this should work:

function fetchData() {
    var queriesRun = 0;
    var allData = [];

    var urls = ["http://stackoverflow.com", 
                "http://stackoverflow.com", 
                "http://stackoverflow.com", 
                "http://stackoverflow.com", 
                "http://stackoverflow.com/thisdoesnotexist"];

    var totalQueries = urls.length;

    var complete = function(jqXHR, textStatus) {
        queriesRun++;
        console.log(queriesRun);

        if(queriesRun == totalQueries) {
           console.log("all done");
           console.log(allData);
        }
    };

    for(var i = 0; i < urls.length; i++) {
        var url = urls[i];
        jQuery.ajax({
           url: url,          
           success: function(data, textStatus, jqXHR) {
              allData.push(data);
           },
           complete: complete
        });
    }
}

Since the complete handler runs after the error and success handler, queriesRun will get incremented each time the AJAX call completes. This handler also checks to see if the number of queries run is equal to the total number of queries. If it is, it will work work with the data.

I've added console.logs in the code so you can easily see what's going on (just run it in firebug).

0

精彩评论

暂无评论...
验证码 换一张
取 消