等到 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 asq
。
谢谢,马特。我编辑了答案来演示 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的主要内容,如果未能解决你的问题,请参考以下文章