在for循环中进行函数调用同步

我在请求中得到一个string数组。 每个string都包含一个要在本机shell上执行的命令。

var process = require('child_process'); function execCommand(req,res,callback){ var params = req.params.list //list is an array in the request var result = ''; var command = ''; for (var i = 0; i < params.length; i++) { command = params[i]; cmd = process.exec(command); cmd.stdout.on('data', function(data){ //push the shell output in variable result }); cmd.on('close', function(code) { //convert the variable result to a valid JSON }); } res.send(result); }; 

所有命令的result混在resultvariables中。 如何使for循环中的函数调用同步?

您可以使用execSync或…

您需要添加一个控制stream库以帮助进行asynchronous调用,以便您可以select以串行或并行方式运行您的函数:

使用execSync而不是exec!

  for (var i = 0; i < params.length; i++) { command = params[i]; result += process.execSync(command).toString(); } 

正如其他人所指出的,这可能不是一个好主意,因为它会阻止事件循环和正在发生的任何请求。 如果正在执行的进程需要很短的时间才能完成,否则是可以接受的。

下面是一个简单的模式来控制for循环中asynchronous函数的stream程…每当进程返回时, params_finished都会增加1。 一旦完成的进程数等于响应发送的进程总数。

  for (var i = 0, total_params=params.length, params_finished=0; i < total_params; i++) { command = params[i]; cmd = process.exec(command); cmd.stdout.on('data', function(data){ //push the shell output in variable result }); cmd.on('close', function(code) { //convert the variable result to a valid JSON params_finished++ if(params_finished == total_params){ res.send(result); } }); } 

另一种方法是在循环内部使用相当于sleep函数。 如果你知道每个循环实例需要多less时间。

 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function myLoopFunction(){ // any code before loop for (var i = 0; i < params.length; i++) { // do whatever await sleep(3000); // 3000 milisecond, for instance } }; 

请参阅此答案以获取有关此方法如何工作的完整说明。