Почему мой javascript / jquery не выполняется последовательно? - PullRequest
4 голосов
/ 31 января 2011

У меня есть кнопка, привязанная к обработчику кликов, который выполняет один или несколько вызовов AJAX в зависимости от количества элементов в массиве. Я использую плагин blockUI jquery , чтобы показать сообщение во время выполнения вызова (вызовов) ajax, затем я показываю результаты и удаляю сообщение blockUI, вызывая $ .unblockUI () ;.

Проблема: По какой-то причине, независимо от того, сколько раз я хочу, чтобы функция ajaxCall выполнялась, после завершения первого вызова ajax сообщение удаляется, даже если цикл все еще продолжает выполняться, и результаты отображаются правильно в #results div. Я хочу, чтобы перед удалением сообщений было выполнено полное число итераций цикла, но похоже, что он не выполняется последовательно. Вот этот код:

$("#myButton").live("click", function(){
    $.blockUI({ message: '<img src="new_loader.gif" /><h2>Getting Config Files</h2><small>Please be patient.</small>',
            css: { 
            border: 'none', 
            padding: '15px', 
            backgroundColor: '#FFF', 
            '-webkit-border-radius': '10px', 
            '-moz-border-radius': '10px',  
            color: '#000' 
            } 
        }); 

    for (var i=0; i< myArray.length; i++)
        {
         ajaxCall(myArray[i]);
        }
    $("#results").show('slow');
    $.unblockUI();  
    return false;
});

Есть ли объяснение, почему код ПОСЛЕ выполнения цикла, даже если цикл еще не завершен? Любая помощь это ценится! Благодаря.

Ответы [ 3 ]

4 голосов
/ 31 января 2011
 ajaxCall(myArray[i]);

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

хороший способ справиться с подобным поведением можно найти в этой статье: Асинхронный метод цепочки очереди методов в JavaScript

2 голосов
/ 31 января 2011

Что бы ни делал ajaxCall(), если он создает XMLHttpRequest асинхронно, это правильное поведение. Ajax-запрос является неблокируемой по умолчанию, я думаю, именно поэтому ваш код после цикла выполняется немедленно.

Один из возможных способов решения этой проблемы - создать переменную счетчика, которая увеличивается при каждом вызове с ajaxCall() и уменьшается в каждом обработчике complete (состояние готовности XHR 4). Когда этот счетчик обнуляется, вы должны выполнить свой код после цикла.

function increase() {      // goes into your `ajaxCall()` or `beforeSend` callback
    mynamespace.requests++;
}

function decrease() {      // goes into your `complete` callbacks
    if(--mynamespace.requests) {
        $("#results").show('slow');
        $.unblockUI();  
    }
}
1 голос
/ 31 января 2011

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

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

var count = arr.length - 1;
for(var i = 0; i < arr.length; i++)
{
    ajaxCall(arr[i], function () {
        if(--count == 0)
        {
            /* All AJAX calls complete, continue execution */
        }
    });
}
...