NODEjs在for循环中同步exec语句

我想创build一个程序,在这里我从目录中读取文件,然后在其他目录中grep这些名称。

这里是代码:

var exec = require('child_process').exec; var internalCount = 0; var i = -1; for (; i < fileNamesInDir.length / 2;) { if (i === internalCount) { continue; } (function () { i = internalCount; var j = i; exec('grep -nre js/' + fileNamesInDir[j] + ' ./ --exclude-dir=node_modules --exclude=searchResults.txt', function (error, stdout, stderr) { outputString += "\n"; outputString += "***********************************************************"; outputString += "\n"; outputString += "RESULTS FOR ::" + fileNamesInDir[j]; outputString += "\n"; outputString += "***********************************************************"; outputString += "\n"; outputString += stdout; outputString += "\n"; if (++internalCount === fileNamesInDir.length) { writeToFile(); } }); })(); } 

问题是执行语句不同步,callback函数asynchronous返回数据。 为了解决这个问题,我已经采取了另一个variables,并继续for循环,如果迭代索引是相同的变种。 但是,使用这段代码,它将进入无限循环,不会执行任何声明。

JavaScript中的for循环同步运行,这是无法告诉它等待循环中的任何东西。 如果你尝试各种黑客攻击,那么由于Javascript的单线程性质,你最终只能碰到路障或无限循环。 所以…基本上你不能让一个循环等待循环内部的asynchronous操作完成,然后再进入循环的下一个迭代。 所以,你必须以不同的方式解决你的问题。


下面是一个通用的scheme,用于在一个接一个地进行操作的情况下进行asynchronous迭代:

 var i = 0; var outputString = ""; function next() { if (i < fileNamesInDir.length) { exec('grep -nre js/' + fileNamesInDir[i] + ' ./ --exclude-dir=node_modules --exclude=searchResults.txt', function (error, stdout, stderr) { outputString += "\n"; outputString += "***********************************************************"; outputString += "\n"; outputString += "RESULTS FOR ::" + fileNamesInDir[i]; outputString += "\n"; outputString += "***********************************************************"; outputString += "\n"; outputString += stdout; outputString += "\n"; i++; next(); }); } else { writeToFile(); } } next(); 

这将连续运行每个grep操作,以便按顺序连接结果。


但是,您不必连续运行这种types的代码。 您可以并行运行所有这些操作,只要按以下顺序收集结果即可:

 var exec = require('child_process').exec; var results = []; var doneCntr = 0; fileNamesInDir.forEach(function(item, index) { exec('grep -nre js/' + item + ' ./ --exclude-dir=node_modules --exclude=searchResults.txt', function (error, stdout, stderr) { var outputString = ""; outputString += "\n"; outputString += "***********************************************************"; outputString += "\n"; outputString += "RESULTS FOR ::" + item; outputString += "\n"; outputString += "***********************************************************"; outputString += "\n"; outputString += stdout; outputString += "\n"; results[index] = outputString; ++doneCntr; if (doneCntr === fileNamesInDir.length) { writeToFile(results.join("")); } }); }); } 

您的代码也缺less需要添加的error handling。


我最喜欢的做法是承诺,让Promise.all()为我们完成收集结果的工作:

 function execP(cmd) { return new Promise(function(resolve, reject) { exec(cmd, function(err, stdout, stderr) { if (err) { reject(err); } else { resolve({stdout, stderr}); } }); }); } Promise.all(fileNamesInDir.map(function(item) { return execP('grep -nre js/' + item + ' ./ --exclude-dir=node_modules --exclude=searchResults.txt').then(function(data) { return "\n" + "***********************************************************\n" + "RESULTS FOR ::" + item + "\n" + "***********************************************************\n" + data.stdout + "\n"; }); })).then(function(results) { var output = results.join(""); // process output here }, function(err) { // process error here });