Серия запросов Ajax не ждет завершения

У меня есть серия вызовов ajax, я хочу, чтобы, когда вызовы завершались, страница перезагружалась, я делаю это

function verifyFrnds() {
    var boxes = $(".matchFrnds:checked").length;
    //alert(boxes);
    var call = 1;
    $(".matchFrnds").each(function (index) {
        if ($(this).is(':checked')) {
            call++;
            var sendData = $(this).val();
            $.post('AJAX PAGE', {
                sendData: sendData
            }, function (data) {
                //window.location.reload();
            });
            //alert(call);
            //alert(call + ' ' + boxes + ' ' + (call >= boxes));
            if (call >= boxes) {
                // window.location.reload();
                alert("I am executed");
            }
        }
    });
}

поэтому, если я делаю предупреждение, то все вызовы ajax выполняются, и мне показывается предупреждающее сообщение, но если я делаю window.localtion.reload(), то после нескольких вызовов ajax страница перезагружается, что должно быть перезагружено после ALL вызовов. Моя основная цель - перезагрузить страницу, когда все вызовы будут выполнены. Любая идея, что я делаю неправильно. По SO уже есть вопрос, но он мне не очень помог.


person Community    schedule 01.12.2013    source источник
comment
jQuerywhen и then api.jquery.com/deferred.then api.jquery.com/jQuery.when   -  person Gaurav Bhor    schedule 01.12.2013
comment
Обратите внимание: вызовы Ajax являются асинхронными, что означает, что они выполняются независимо от любого другого процесса. Это означает, что если вы хотите последовательно вызывать Ajax, вам придется использовать обратный вызов   -  person Richard Peck    schedule 01.12.2013


Ответы (4)


Попробуйте использовать $.when:

function verifyFrnds() {
    var deferreds = []; //using an array to save promise interfaces
    $(".matchFrnds").each(function (index) {
        if ($(this).is(':checked')) {
            var sendData = this.value;
            //we push each request in array (returned promise interface)
            deferreds.push($.post('AJAX PAGE', {
                sendData: sendData
            }));
        }
    });
    //as $.when only accept deferred(promise) as arguments, we need to apply $.when to each promise of array
    $.when.apply(null, deferreds).done(function () {
        alert("I am executed once all requests done (success)");
        window.location.reload();
    });
}
person A. Wolff    schedule 01.12.2013
comment
Хотя это лучшее решение проблемы, оно не имеет абсолютно никакого смысла без каких-либо объяснений. - person m90; 01.12.2013
comment
@A Wolff ведет себя очень странно, иногда он выполняет все вызовы ajax, а иногда выполняет очень мало. - person ; 01.12.2013
comment
Проверьте вкладку сети на наличие отклоненных запросов (возможно, слишком много параллельных запросов). В идеале вы должны сделать только один запрос к серверу, чтобы отправить/получить все данные сразу. - person A. Wolff; 01.12.2013
comment
@A.Wolff A.Wolff Я проверил консоль, и на самом деле она не сделала запрос, похоже, что массив не заполнен правильным значением .. - person ; 01.12.2013

Так же, как А. Вольф советовал использовать jQuery.when и jQuery.then.

Другая альтернатива: вызвать метод по завершении ajax (метод jqXHR всегда). Проверьте, вызывают ли поля call >= (или любое другое условие, которое вам нравится) в этом методе. Для меня это немного легко понять по сравнению с другим решением.

function verifyFrnds() {
    var boxes = $(".matchFrnds:checked").length;
    //alert(boxes);
    var call = 1;
    $(".matchFrnds").each(function (index) {
        if ($(this).is(':checked')) {
            //call++; Move it to .always Thanks for pointing out Khanh
            var sendData = $(this).val();
            $.post('AJAX PAGE', {
                sendData: sendData
            }, function (data) {
                //window.location.reload();
            }).always ( function() {  
                // This method will be called on ajax completion. be it a failure or success.
                // see .done ( for success only )  ; .fail ( for failure only )
                call++;
                if (call >= boxes) {
                  // window.location.reload();
                   alert("I am executed");
                }
            }   ;


        }
    });
}

Подробнее об объекте jqXHR. Читайте: http://api.jquery.com/jQuery.ajax/#jqXHR

person Rakesh Juyal    schedule 01.12.2013
comment
та же проблема, он выполнил 7 вызовов из 42 и перезагрузил страницу - person ; 01.12.2013
comment
@ user1765876: попробуйте поставить call++; внутри .always перед if (call >= boxes) { - person Khanh TO; 02.12.2013
comment
@ user1765876: в функции ошибка. Я думаю, это должно быть $(".matchFrnds:checked").each вместо $(".matchFrnds").each - person Khanh TO; 07.12.2013

Вы можете связать свой вызов ajax, используя $.then, если вам нужно сделать это последовательно. Так:

function verifyFrnds() {
    var d = jQuery.Deferred();
    var p=d.promise();

    $(".matchFrnds:checked").each(function (index) {//instead of .matchFrnds
        if ($(this).is(':checked')) {

            var sendData = $(this).val();
            p.then($.post('AJAX PAGE', {
                sendData: sendData
              }, function (data) {
                //window.location.reload();
              })
            );
        }
    });

    p.then(function(){
         alert("I am executed");
    });
    d.resolve();
}

Обратите внимание, что для jQuery до версии 1.8 вы должны использовать .pipe вместо .then. Также проверьте свой код, я думаю, что это ошибка, должно быть $(".matchFrnds:checked").each( вместо $(".matchFrnds").each(

person Khanh TO    schedule 01.12.2013

Вы должны увеличивать call не после if, а в случае успеха ваших вызовов ajax.

Я советую вам поместить вызов перезагрузки в функцию, которую вы вызываете с помощью setInterval, а не в успешном возврате ajax.

person vekah    schedule 01.12.2013