如何知道异步for循环何时完成?

4
我有一个for循环,它会启动数百个异步函数。一旦所有函数完成,我需要运行最后一个函数,但我似乎无法理解什么时候所有函数都完成。
我尝试过使用promises,但只要循环中的任何一个函数解析,我的promise函数就会完成。
for(var i = 0; i < someArray.length; i ++){
// these can take up to two seconds and have hundreds in the array
asyncFunction(someArray[i];
} 

如何判断所有函数是否已完成?


你可能想要研究一下"Promise"(承诺)相关的内容。 - scunliffe
2
你正在寻找 Promise.all: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all - Felix Kling
1
你应该收集一个承诺数组,对于循环中每次调用异步函数都需要一个承诺,然后在传递给 Felix King 链接的 Promise.all 方法之后。 - xkickflip
3个回答

4

增量

您可以添加一个回调函数来进行增量操作:

for (var i = 0; i < len; i++) {
    asycFunction(someArray[i]);
    asycFunction.done = function () {
        if (i == someArray.length - 1) {
            // Done with all stuff
        }
    };
}

递归方法

这种方法更受一些开发人员的青睐,但可能需要更长的执行时间,因为它等待一个完成后才运行另一个。

var limit = someArray.length, i = 0;

function do(i) {
    asyncFunction(someArray[i]);
    asyncFunction.done = function () [
        if (i++ == someArray[i]) {
            // All done!
        } else { do(i); }
    }
}
do(i++);

承诺

目前承诺(Promises)的支持还不太好,但是你可以使用一个库。不过这肯定会增加页面的大小。


一个很好的解决方案

(function (f,i) {
    do(i++,f)
}(function (f,i) {
    asyncFunction(someArray[i]);
    asyncFunction.done = function () {
        if (i++ === someArray.length - 1) {
            // Done
        } else { f(i) }
    };
}, 0)

我实际上尝试了你的第一个建议,使用增量。但我遇到的问题是for循环启动异步函数后就不等待而是再次循环。因此,当if语句为true时,这只意味着循环已经完成启动异步函数,而不是它们已经完成。 - Skej
@Skej 这正是第二种解决方案的目的。尝试一下,希望它能起作用。 - Downgoat
递归方法解决了它。我曾经想过这个方法,但它似乎像是一个临时的解决方案,但如果看起来很蠢但却能正常工作,那么它就不是蠢办法。 - Skej
1
@Skej 我添加了一种更好的、非doct-tape解决方案。它使用匿名函数,这些函数更容易重用而不需要进行大量修改。 - Downgoat

3
许多库有.all解析器:

您可以使用它们或学习它们的源代码。

假设这段代码是函数foo() 的主体:

function foo() {
    return Promise.all(someArray.map(function(item) {
        //other stuff here
        return asyncFunction(item, /* other params here */);
    }));
}

或者,如果没有其他要做的事情,并且没有其他参数要传递:

function foo() {
    return Promise.all(someArray.map(asyncFunction));
}

1
你可以检查响应数量。
对于每个响应,您可以增加计数器值,如果计数器值与someArray.length相同,则可以假定所有异步函数都已完成,并且可以开始下一步。

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