我有以下代码:
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
了。建议?
答案 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。