Выполнение последовательных операций в node.js - PullRequest
1 голос
/ 05 декабря 2010

У меня есть асинхронная функция, которая выполняет некоторые команды оболочки параллельно

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

Я хочу сделать что-то после , эти команды оболочки будут выполнены, но я не могу понять, как это сделать с помощью асинхронной библиотеки. Эти команды оболочки выполняются параллельно, поэтому невозможно зарегистрировать обработчик, который выполняется после . Все они выполняются.

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 05 декабря 2010

Использование библиотеки 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
    })
});
3 голосов
/ 05 декабря 2010

Обновление

После того, как вы отредактировали свой вопрос, чтобы показать действительный код, это должно работать:

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

При запуске:

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!

Старый ответ

Я полагаю, вы используете модуль child_process.

Вам необходимо создать оболочку для ваших команд.

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

Это запустит все 3 команды, две ls завершатся мгновенно, sleep задержит все на 1 секунду, после этого будет вызван обратный вызов.

Я думаю, это также возможнос Futures , но это, скорее всего, перебор в этой ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...