为什么我的JavaScript/jQuery代码没有按顺序执行?

4

我有一个按钮绑定了一个点击处理程序--根据数组中有多少项,会进行一个或多个AJAX调用。我使用blockUI jQuery插件在ajax调用时显示消息,然后显示结果,并通过调用$.unblockUI();移除blockUI消息。

问题: 由于某种原因,在第一个ajax调用完成后,无论我想让ajaxCall函数执行多少次,消息都被删除了,尽管循环仍然继续执行,结果在#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;
});

循环尚未完成,为什么循环之后的代码正在执行?请帮忙解答!谢谢。

1
你确定循环没有完成吗?Ajax调用需要一些时间,如果它们仍在运行,循环可能已经结束了。 - goto-bus-stop
2
最好的做法是使用完整序列化数组进行单个请求,并在(单一)请求的回调函数中取消接口的阻塞。 - karim79
3个回答

4
 ajaxCall(myArray[i]);

这个方法是异步完成的,因此该方法在循环内被触发,但执行需要更多时间,因此会在代码的其余部分结束后结束。

处理此类行为的好方法可以在此文章中找到:JavaScript中的异步方法队列链接


2
无论ajaxCall()做了什么,如果它异步地创建了一个XMLHttpRequest,那么这是正确的行为。Ajax请求默认是非阻塞的,我猜这就是你的循环后面的代码立即执行的原因。
我能想到的一种可能的解决方法是创建一个计数器变量,每次从ajaxCall()调用时增加,并在每个complete处理程序(XHR readystate 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();  
    }
}

这里需要调用两次减法。在检查是否为零之前需要先进行减法运算。 - Josh K

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接