Выполните множество запросов AJAX параллельно и запустите функцию после того, как все они завершены - PullRequest
6 голосов
/ 25 апреля 2011

Я пытаюсь выполнить следующую последовательность операций с использованием JQuery в HTML.

  • Составлен список URL-адресов
  • Каждый из этих URL-адресов запрашивается с использованием $ .getJSON.(url) параллельно
  • Ожидание завершения или сбоя всех запросов (может произойти 404)
  • Возьмите данные всех выполненных JSON-запросов и сделайте что-нибудь.

Я создал код Java-Script, размещенный ниже.Он работает безупречно, за исключением случаев, когда один из запросов завершается неудачно из-за ошибки 404: тогда $.when не запускается, потому что он мгновенно прерывается при сбое запроса.Можете ли вы как-то переопределить ajax-запросы, чтобы они не потерпели неудачу, а вместо этого возвратили пустой источник?

Я уже прочитал эту и эту запись, но этоне предоставляет решение, где код может быть запущен после завершения всех запросов.

function fetchData() {
    queries = [];
    //urls is initialized somewhere else containing all urls
    for(var url in urls) {
        queries.push($.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!
 }

Ответы [ 3 ]

2 голосов
/ 25 апреля 2011

Я мог бы сделать что-то вроде этого:

$(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');
        }
    }
});

Здесь вы помещаете данные из ошибки или в массив _d и проводите тестирование, чтобы убедиться, что выВы получили все ответы, прежде чем продолжить (alert('were done');).

Конечно, вы можете сделать это умнее, поместив объект, содержащий состояние op вместе с полезной нагрузкой, в _d, но это был быстрый взломвместе, чтобы продемонстрировать, как я, скорее всего, буду делать то, что вы спрашиваете.

Fiddle здесь

1 голос
/ 25 апреля 2011

Примерно так должно работать:

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

Поскольку обработчик complete запускается после обработчиков error и success, queriesRun будет увеличиваться при каждом завершении вызова AJAX. Этот обработчик также проверяет, равно ли количество выполненных запросов общему количеству запросов. Если это так, он будет работать с данными.

Я добавил console.log s в код, чтобы вы могли легко видеть, что происходит (просто запустите его в firebug).

1 голос
/ 25 апреля 2011

Примерно так:

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

Вам нужно проверить спецификацию jQuery ajax о том, как точно ее вызвать и как обрабатывать ошибки (т. Е. Как указать обратный вызов ошибки), но этоне должно быть слишком сложно изменить код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...