等到 for 循环内的所有函数调用结束其执行 - Javascript

Posted

技术标签:

【中文标题】等到 for 循环内的所有函数调用结束其执行 - Javascript【英文标题】:Wait until all the function calls inside for-loop ends its execution - Javascript 【发布时间】:2014-09-13 10:38:28 【问题描述】:

我有一个函数,它在 for 循环中包含另一个函数调用。

outerFunction() 
    for (var j = 0; j < geoAddress.length; j++) 
         innerFunction(j);
    

我需要等到对 innerFunction 的所有调用完成。如果我需要并行执行这些函数,如何在 javascript 中实现呢?

【问题讨论】:

您能提供您的innerFunction 正文吗? 所以innerFunction 被线程化了? 假设 innerFunction 在异步中,使用“promises”,例如github.com/kriskowal/q 您知道node.js 是单线程的,所以即使您异步执行innerFunction,每次也只会执行其中一个方法。?什么是内部函数?它会调用单独的服务或进程吗?它是如何工作的? 我的内部功能是查询一个 mongoDB 数据库。根据 j ,内部函数从不同的 mongoDB 数据库中检索数据。最后,我需要汇总所有这些。 【参考方案1】:

如果您不想为此使用外部库,您可以创建一个范围对象,例如 process,它会跟踪有多少 innerFunction 调用仍处于未决状态,并在等待时调用外部回调 cb完成了。

这样做的重点是您仍然可以获得异步执行的好处,但您只需确保您的代码在属于 outerFunction 的所有 innerFunction 实际完成之前不会执行下一部分:

outerFunction(function() 
    console.log("All done for outerFunction! - What you should do next?");

    // This block is executed when all innerFunction calls are finished.

);

JavaScript:

// Example addresses
var geoAddress = ["Some address X", "Some address Y"];

var innerFunction = function(geoAddress, process)  

    // Your work to be done is here...
    // Now we use only setTimeout to demonstrate async method
    setTimeout(function() 

        console.log("innerFunction processing address: " + geoAddress);

        // Ok, we update the process
        process.done();   

    , 500);

;

var outerFunction = function(cb)  

    // Process object for tracking state of innerFunction executions
    var process =  

        // Total number of work ahead (number of innerFunction calls required).
        count: geoAddress.length,

        // Method which is triggered when some call of innerFunction finishes  
        done: function() 

            // Decrease work pool
            this.count--;

            // Check if we are done & trigger a callback
            if(this.count === 0)  
                setTimeout(cb, 0);
                        
        
    ;

    for (var j = 0; j < geoAddress.length; j++) 
        innerFunction(geoAddress[j], process);
    

;

// Testing our program
outerFunction(function() 
    console.log("All done for outerFunction! - What you should do next?");

    // This block is executed when all innerFunction calls are finished.

);

输出:

innerFunction processing address: Some address X
innerFunction processing address: Some address Y
All done for outerFunction! - What you should do next? 

这里是js fiddle example

干杯。

【讨论】:

【参考方案2】:

编辑 - 使用 Q Promise 库以节点方式做事

如果您使用的是 Q Promise 库,请尝试以下操作:

outerFunction()
    var promises = [];

    for (var j = 0; j < geoAddress.length; j++) 
        deferreds.push(innerFunction(j));
    

    Q.all(promises).then(function() 
        // do things after your inner functions run 
    );

即使您不使用这个特定的库,原理也是一样的。一个人应该让一个函数返回一个 Promise 或者像 Q.denodify 方法一样将它包装在一个 Promise 中,将所有调用推送到一个 Promise 数组,将所述数组传递给你的库的等效 .when() (jQuery) 或 .all () (Q Promise 库),然后在所有 Promise 都解决后使用 .then() 来做事。

【讨论】:

他正在使用 NodeJS,所以他不太可能会使用 jQuery。不过,还有其他延迟/承诺实现,such as q 谢谢,马特。我编辑了答案来演示 Q 的 all() 方法的用户。【参考方案3】:
outerFunction()  
    var done = 0;

    function oneThreadDone() 
        done++;
        if (done === geoAddress.length) 
            // do something when all done
        
    

    for (var j = 0; j < geoAddress.length; j++) 
         setTimeout(function()  innerFunction(j, oneThreadDone); , 0);
    

并在 inner_function 内部调用 oneThreadDone() 函数(通过参数传递引用)

【讨论】:

【参考方案4】:

查看异步库。 https://www.npmjs.org/package/async

查看有关“同时”的文档。听起来它可以满足您的需求。 同时(测试,fn,回调)

var count = 0;

async.whilst(
function ()  return count < 5; ,
function (callback) 
    count++;
    setTimeout(callback, 1000);
,
function (err) 
    // 5 seconds have passed

);

【讨论】:

我认为这里的问题是,如果方法被两个不同的用户请求调用,那么这两个请求都会改变 count 的值,因为它被定义为 var count = 0;而不是属于某个对象实例。 (?) 这个问题可以用async.forEach完美解决。你为什么用whilst发布不相关的代码? 他没有遍历 geoAddress 数组中的每个对象,而是使用索引整数调用他的 innerFunction。 forEach 似乎不像 while 那样适合他的用例。

以上是关于等到 for 循环内的所有函数调用结束其执行 - Javascript的主要内容,如果未能解决你的问题,请参考以下文章

Vue 在页面加载结束后执行某个函数

返回函数的返回值的return和结束for循环的return是一个东西吗?

在 for 循环中的异步函数调用中有条件地执行回调

Node.js 等到异步函数完成,然后继续执行其余代码

Node.js 等到异步函数完成,然后继续执行其余代码

DAY 04 while和for循环