NODEjs在for循环中同步exec语句

时间:2016-07-11 06:57:39

标签: javascript node.js exec fs

我想创建一个程序,在其中我从目录中读取文件,然后在其他目录中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();
        }
      });
  })();
}

问题是execute语句不是同步的,并且回调函数异步返回数据。为了解决这个问题,我已经采用了另一个变量并继续for循环,如果迭代索引与该var相同。但是,使用此代码,它将进入无限循环,不会触发exec语句。

1 个答案:

答案 0 :(得分:4)

Javascript中的for循环同步运行,这里无法告诉它等待循环中的任何内容。如果您尝试各种黑客攻击,由于Javascript的单线程特性,您最终会遇到障碍或无限循环。所以......基本上你不能让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(); 循环等待循环内的异步操作完成,然后再进入循环的下一次迭代。所以,你必须以不同的方式解决你的问题。

这是一种常见的迭代迭代方案,其中操作协调并一个接一个地完成:

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(""));
            }
        });
    });
}

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

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

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 }); 为我们收集结果的工作:

$_POST['From'] = "'".date('Y-d-m H:i:s', strtotime(str_replace('-', '/', $_POST['From'])))."'";   

$_POST['To']= "'".date('Y-d-m H:i:s', strtotime(str_replace('-', '/', $_POST['To'])))."'";   
相关问题