2016-07-11 3 views
1

디렉토리 안의 파일을 읽은 다음 다른 디렉토리에서 해당 이름을 grep하는 프로그램을 만들고 싶습니다.for 루프 내에서 NODEjs exec 문을 동기화합니다.

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

문제가 실행 문 동기하지 않은 콜백 함수 비동기 데이터를 반환한다는 것이다 : 여기

코드이다. 이 문제를 해결하기 위해 다른 변수를 가져 와서 iterating 인덱스가 var와 동일한 경우 for 루프를 계속 수행합니다. 그러나이 코드를 사용하면 실행 문이 실행되지 않아 무한 루프가됩니다.

+1

당신이'i'를 증가되는 경우? – thefourtheye

+0

예 .. 일단 콜백 함수가 실행되면 .. 내부 카운트가 증가됩니다. 그래서 다음 반복을 위해 나는 internalCount와 같지 않습니다. 그런 다음 계속 실행되지 않고 자체 실행 함수가 실행됩니다. –

답변

2

for 자바 스크립트에서 루프가 동 기적으로 실행되며 루프에서 아무 것도 기다리지 않도록 할 방법이 없습니다. 다양한 해킹을 시도하면 Javascript의 단일 스레드 속성으로 인해로드 블록 또는 무한 루프로 실행됩니다. 그래서 ... 기본적으로 for 루프는 비동기 작업이 완료 될 때까지 기다렸다가 루프의 다음 반복을 진행할 수 없습니다. 따라서 문제를 다른 방식으로 해결해야합니다.


여기에 작업을 하나씩 조정 및 수행되는 경우 비동기 적으로 반복위한 공통 구조입니다 : 결과가 순서대로 연결됩니다 있도록이 직렬은 grep 각 작업을 실행

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

귀하의 코드도없는 오류 처리. 이 작업을 수행하는


내가 가장 좋아하는 방법은 약속이며, 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 
}); 
관련 문제