4

我有一个与单击处理程序相关联的按钮——它会进行一个或多个 AJAX 调用,具体取决于数组中有多少项。我使用blockUI jquery 插件在进行 ajax 调用时显示一条消息,然后显示结果,并通过调用 $.unblockUI(); 删除 blockUI 消息。

问题: 由于某种原因,无论我希望 ajaxCall 函数执行多少次,在 FIRST 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;
});

即使循环尚未完成,是否有解释为什么循环执行后的代码?任何帮助表示赞赏!谢谢。

4

3 回答 3

4
 ajaxCall(myArray[i]);

异步完成的,因此该方法在循环内被触发,但执行将花费更多时间,因此在其余代码完成后结束。

在这篇文章中找到了一种处理这种行为的好方法:JavaScript 中的异步方法队列链接

于 2011-01-31T18:32:42.843 回答
2

不管做什么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();  
    }
}
于 2011-01-31T18:32:19.300 回答
1

我猜那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 */
        }
    });
}
于 2011-01-31T18:32:42.703 回答