2010-12-05 4 views
1

J'ai une fonction async qui exécute des commandes shell en parallèleExécution des opérations en série dans Node.js

require("fs").readdir("./", function (error, folders) { // asynched 
    require("underscore")._(folders).each(function (folder, folderKey, folderList) { // asynched 
    r("child_process").exec("ls ./" + folder, function(error, stdout, stderr) { 
      console.log("Cant put it here") // Will be run after the first execution is completed 
     }) 
     console.log("Cant put it here either") // Will be run immediately before any execution is completed 
    }) 
    console.log("Cant put it here either") // Will be run immediately before any execution is completed 
}) 

Je veux faire quelque chose après les commandes shell sont exécutées, mais je ne peux pas savoir comment faire ceci avec la bibliothèque asynchrone. Ces commandes shell sont exécutées en parallèle, donc il n'y a aucun moyen d'enregistrer un gestionnaire qui est exécuté après tous sont exécutés.

Des idées?

+0

Merci pour montrer le code maintenant, je l'ai mis à jour ma réponse avec une solution adaptée. –

Répondre

3

Mise à jour

Après avoir modifié votre question pour montrer votre code actuel, cela devrait fonctionner:

var ps = require('child_process'); 
var fs = require('fs'); 
var _ = require("underscore"); 

function listDirectory(dir, callback) { 
    fs.readdir(dir, function (error, folders) { 

     // simply keep track on how many of the ls's have finished 
     var count = folders.length, done = 0; 
     _(folders).each(function (folder, folderKey, folderList) { 
      ps.exec("ls ./" + folder, function(error, stdout, stderr) { 
       console.log('one more done'); 
       done++; 
       if (done === count) { 
        callback(); 
       } 
      }); 
     }); 
    }) 
} 

listDirectory('./', function() { 
    console.log('all done!'); 
}); 

Exécuté:

one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
one more done 
all done! 

Vieille réponse

Je suppose que vous utilisez le module child_process.

Vous devez créer un wrapper autour de vos commandes.

var spawn = require('child_process').spawn; 


// this function will execute all the things in the cmds array 
// after all the processes have exited, it will call the callback 
function multiSpawn(cmds, callback) { 
    var count = cmds.length; 
    var done = 0; 
    for(var i = 0; i < count; i++) { 
     // spawn the process, modify this if you need to hook up further events 
     // you could also pass in further functions to setup each spawn 

     var ps = spawn(cmds[i].shift(), cmds[i]); 
     ps.on('exit', function() { 
      done++; // keep track on how many commands have finished 
      if (done === count) { 
       callback(); 
      } 
     }); 
    } 
} 

multiSpawn([ 
    ['ls', '/usr/lib', '-l'], 
    ['sleep', '1'], // this will sleep 1 seconds 
    ['ls', '/usr/share', '-a'] 

], function() { 
    console.log('all done'); 
}); 

Cela exécutera toutes les 3 commandes, les deux ls termineront instantanément, sleep retardera tout pour 1 secondes, après que le rappel est appelé.

Je suppose que ce serait également possible avec Futures, mais c'est probablement trop dans cette situation.

5

Utilisation de la bibliothèque de async.js: https://github.com/caolan/async

var fs = require('fs'); 
var async = require('async'); 
var exec = require('child_process').exec; 

fs.readdir("./", function (error, folders) { 
    async.forEach(folders, function (folder, callback) { 
     exec("ls ./" + folder, function (error, stdout, stderr) { 
      callback(); 
     }); 
    }, 
    function (error) { 
     // this is called after all shell commands are complete 
    }) 
}); 
+0

Maintenant, je comprends pourquoi ces fonctions sont bonnes =) – ajsie