简体   繁体   English

在node.js中运行串行操作

[英]Running serial operations in node.js

I have an async function that executes some shell commands in parallel 我有一个异步函数,可以并行执行一些shell命令

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

I want to do something after those shell commands are executed but I cant figure out how to do this with async library. 我想在执行完这些shell命令做一些事情但是我无法弄清楚如何使用异步库做到这一点。 Those shell commands are executed in parallel, so there is no way to register a handler that is executed after all of them are executed. 这些shell命令是并行执行的,因此无法注册所有命令执行执行的处理程序。

Any ideas? 有任何想法吗?

Using the async.js library: https://github.com/caolan/async 使用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
    })
});

Update 更新资料

After you edited your question to show your actual code, this should work: 在您编辑问题以显示您的实际代码之后,这应该可以工作:

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

When run: 运行时:

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!

Old answer 旧答案

I suppose your using the child_process module. 我想您使用child_process模块。

You need to create a wrapper around your commands. 您需要围绕命令创建包装器。

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

This will run all the 3 commands, the two ls will finish instantly, sleep will delay everything for 1 second, after that the callback gets called. 这将运行所有3个命令,两个ls将立即完成,在调用回调之后, sleep将使所有内容延迟1秒。

I guess this would also be possible with Futures , but that's most likely overkill in this situation. 我想使用Futures也是可能的,但是在这种情况下,这很可能是过大了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM