上一篇文章完成后如何运行代码?

时间:2013-01-05 01:36:38

标签: javascript jquery

我有以下代码:

for (var i = 0; i < numFiles; i++) {
    $.post('/Secure/File/PhysicalFileHandler.ashx?custId=whatever&idx=' + i, function (data) {
        ids += data + '|';
        if (i == numFiles-1) {
            ids = ids.substring(0, ids.length - 1);
        }
    });

}

如何在上一篇文章结束后执行一大堆代码?我上面尝试的方法不起作用(i已经==numFiles了。建议?

2 个答案:

答案 0 :(得分:2)

这是一个有点常见的问题 - 你引用的“i”由for函数处理,并且通常for函数在触发回调时已经完成执行(在这种情况下,“i”是相等的到numFiles已经)。这有几个解决方案:一个是将回调更改为:

(function (i) {
  return function (data) {
    ids += data + '|';
    if (i == numFiles-1) {
        ids = ids.substring(0, ids.length - 1);
    }
})(i)

这样做是为循环的每次执行创建一个新函数,每次函数都有自己对“i”的引用 - 而不是回顾for循环的i的定义/值,它有它自己的要引用的局部参数。这必须通过返回另一个函数来完成,因为您需要在for循环的第一次传递期间执行代码,确保在触发回调时保留正确的值。

另一种选择是将整个post语句用它自己的i副本包装在一个函数中 - 我不认为两者之间有太大的区别。就个人而言,我更倾向于上述代码段中的方法,因为它最大限度地减少了代码整体流程的影响,但意见会有所不同。

答案 1 :(得分:0)

帖子可能无法按照启动顺序完成。你必须在完成后计算每一个,以便知道所有的都已完成。

var finishedCount = 0; // track number of calls finished
for (var i = 0; i < numFiles; i++) {
    (function(i) {
        $.post('/Secure/File/PhysicalFileHandler.ashx?custId=whatever&idx=' + i, function (data) {
            ids += data + '|';
            finishedCount = finishedCount + 1; // increment number of calls finished
            if (finishedCount == numFiles) { // run only when all calls have finished
                ids = ids.substring(0, ids.length - 1);
            }
        });
    })(i); // capture value of i in closure
}

编辑:不再需要在闭包中捕获i的值,因为在此版本的post回调函数中没有使用i。