2013-01-18 14 views
8

Z góry dziękuję za spojrzenie na to.Węzeł Grunt Asynchronous Zadanie w pętli z zamknięciem nie działa

Mam zadanie asynchroniczne w pętli, która nie działa. Zrobiłem pamiętaj o:

  1. owinąć pętli „klucz” zmienny w zamknięciu, aby uniknąć klasycznego „ostatnią wartość tylko” problem, gdzie pętla kończy długo zanim zadań asynchronicznych zwraca wartość, a jedynie wyświetlana jest ostatnia wartość.
  2. Zaproszenie zrobić (błąd), aby zakończyć swoje zadanie asynchronicznej (na tej Gruntjs FAQ)
  3. Zastosowanie hasOwnProperty(), aby upewnić się, że klucz jest rzeczywista własność przedmiotu, a nie pochodzi od prototypu.
  4. Postępuj zgodnie z formatem przykładu node.exec, z wyjątkiem przypisania wartości exec do zmiennej - którą próbowałem, ale to nie pomogło. Zobacz pierwsze odniesienie poniżej.

Ta funkcja wyświetla ... nic !? Z jakiegoś powodu instrukcje grunt.log.writeln nawet nie zwalniają. Zadanie kończy się bez błędów. Próbowałem też dodać 20-sekundowe opóźnienie, na wypadek gdyby skrypt został zakończony przed zwróceniem zadania asynchronicznego. Dziwnie, jeśli nie nazywam "done (error)", pliki są zapisywane do pliku (gdy zastępuję writeln za pomocą instrukcji grunt.file.write).

var done = this.async(), 
    exec = require('child_process').exec, 
    myJSON = { 
     "file1" : "C:/home/me/jquery.js", 
     "file2 " : "C:/home/me/grunt.js", 
     ... 
     "fileN" : "C:/home/me/N.js" 
    }, 
    count; 

for (var key in myJSON) { 
    if (myJSON.hasOwnProperty(key)) { 
     (function (key) { 
     exec('type "' + myJSON[key] + '"', 
      function(error, stdout, stderr) { 
      if (error) { 
       grunt.log.writeln('!!! exec error: ' + error); 
      } 
      grunt.log.writeln('stdout: ' + stdout); 
      grunt.log.writeln('stderr: ' + stderr); 
      done(error); 
      } 
     ); 
     })(key); 
    count++; 
    } 
} 

Referencje:

http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback https://github.com/gruntjs/grunt/wiki/Frequently-Asked-Questions

Odpowiedz

12

done() powinna nazywać się tylko wtedy, gdy cała operacja jest zakończona, co oznacza, gdy wszystkie metody exec() wyczerpał swoje zwrotnych. Aktualnie wykonujesz wywołanie zwrotne done w każdej iteracji. można łatwo osiągnąć za pomocą metody forEach w module węzła async która pochodzi z pomrukiem (grunt.util.async (lub forEachSeries jeśli chcesz exec() metody wykonywane w kolejności

Coś takiego (nie sprawdzone).

var done = this.async(); 
var exec = require('child_process').exec; 
var async = grunt.util.async; // updated 
var myJSON = { 
    "file1": "C:/home/me/jquery.js", 
    "file2": "C:/home/me/grunt.js", 
    ... 
    "fileN": "C:/home/me/N.js" 
}; 

async.forEach(Object.keys(myJSON), function(el, cb) { 
    exec('type "' + myJSON[el] + '"', function(error, stdout, stderr) { 
     if (error) { 
      grunt.warn('!!! exec error: ' + error) 
      return cb(error); 
     } 
     grunt.log.writeln('stdout: ' + stdout); 
     grunt.log.writeln('stderr: ' + stderr); 
     cb(); 
    } 
); 
}, function(error) { 
    done(!error); 
}); 
+0

tyvm. Najczęściej zadawane pytania doprowadziły mnie do przekonania, że ​​done() trzeba było wywołać dla _each_ asych operacji w ramach zadania.To była bardzo pomocna, doceniam twój czas :). – user1354017

+0

Więc, na wynos tutaj jest że narzędzia grunt.utils.goync są preferowane do pracy z zadaniami asynchronicznymi - w przeciwieństwie do ręcznego tworzenia zamknięć itd., poprawne? – user1354017

+0

To jest cor rect, ale nie tylko do chrząknięcia. Jest nieoceniony podczas pracy w Node.js w ogóle. https://github.com/caolan/async –

Powiązane problemy