2016-07-11 28 views
1

Ich möchte ein Programm erstellen, in dem ich die Dateien aus einem Verzeichnis lesen und dann diese Namen in anderen Verzeichnissen grep. HierNODEjs Exec-Anweisungen innerhalb von for Schleife synchronisieren

ist der Code:

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

Das Problem ist, dass die ausführen Aussagen nicht synchron sind und die Callback-Funktionen Daten asynchron zurück. Um dies zu lösen, habe ich eine andere Variable genommen und setze die for-Schleife fort, wenn der Iterationsindex derselbe ist wie der var. Mit diesem Code geht es jedoch in die Endlosschleife, ohne dass exec-Anweisungen ausgelöst werden.

+1

Wo Sie Inkrementieren 'I'? – thefourtheye

+0

ja .. sobald die Callback-Funktion ausgeführt wird..internalcount wird inkrementiert. Für die nächste Iteration bin ich also nicht gleich internalCount und dann würde die Fortsetzung nicht passieren und die selbstausführende Funktion würde laufen –

Antwort

2

Eine for Schleife in Javascript läuft synchron und hier ist keine Möglichkeit, es auf etwas in der Schleife zu warten. Wenn Sie verschiedene Hacks ausprobiert haben, stolpern Sie aufgrund von Javascript nur in Roadblocks oder Endlosschleifen. Also ... im Grunde können Sie nicht eine for Schleife warten auf eine asynchrone Operation innerhalb der Schleife zu beenden, bevor Sie zur nächsten Iteration der Schleife gehen. Also musst du dein Problem auf andere Weise lösen.


Hier ist ein gemeinsames System asynchron zur Iteration wo Operationen koordiniert werden und einer nach dem anderen getan:

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

Dies wird jeder der grep Operationen seriell ausgeführt werden, damit die Ergebnisse, um verkettet.


Aber Sie müssen diese Art von Code nicht seriell ausführen. Sie können alle diese Operationen parallel ausgeführt werden, solange Sie die Ergebnisse, um wie folgt zu sammeln:

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

Ihr Code wird auch die Fehlerbehandlung fehlt, die hinzugefügt werden muss.


Mein Liebling Weg, dies mit dem Versprechen zu tun ist, und lassen Sie Promise.all() die Arbeit machen von Ergebnissen, um für uns zu sammeln:

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