Node.js 如何按顺序执行shell命令?

Node.js 如何按顺序执行shell命令?,node.js,shell,Node.js,Shell,我有一个要使用nodejs执行的shell命令列表: // index.js var commands = ["npm install", "echo 'hello'"]; var exec = require('child_process').exec; for (var i = 0; i < commands.length; i++) { exec(commands[i], function(err, stdout) { console.log(stdout

我有一个要使用nodejs执行的shell命令列表:

// index.js
var commands = ["npm install", "echo 'hello'"];

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

for (var i = 0; i < commands.length; i++) {
    exec(commands[i], function(err, stdout) {
        console.log(stdout);
    });
}
//index.js
var命令=[“npm安装”,“echo'hello'”;
var exec=require('child_process')。exec;
for(var i=0;i
当我运行这个命令时,命令是以相反的顺序执行的。为什么会这样?如何按顺序执行命令

更好的是,有没有一种不使用nodejs执行shell命令的方法?我发现它对shell的异步处理有点麻烦

注:


我知道像
shelljs
这样的库是存在的。我仅尝试使用基本节点执行此操作。

您的
for
循环一次并行执行所有异步操作,因为
exec()
是非阻塞的。他们将完成的顺序取决于他们的执行时间,而不是确定的。如果你真的希望它们被排序,那么你必须执行一个,等待它调用它的完成回调,然后执行下一个

不能使用传统的
for
循环“等待”异步操作在Javascript中完成,以便按顺序执行它们。相反,您必须手动进行迭代,在上一个迭代的完成回调中启动下一个迭代。我通常的做法是使用计数器和名为
next()
的本地函数,如下所示:

手动异步迭代

var commands = ["npm install", "echo 'hello'"];

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

function runCommands(array, callback) {

    var index = 0;
    var results = [];

    function next() {
       if (index < array.length) {
           exec(array[index++], function(err, stdout) {
               if (err) return callback(err);
               // do the next iteration
               results.push(stdout);
               next();
           });
       } else {
           // all done here
           callback(null, results);
       }
    }
    // start the first iteration
    next();
}

runCommands(commands, function(err, results) {
    // error or results here
});

蓝鸟承诺

使用Bluebird promise库,这将更加简单:

var Promise = require('bluebird');
var execP = Promise.promisify(require('child_process').exec);

var commands = ["npm install", "echo 'hello'"];
Promise.mapSeries(commands, execP).then(function(results) {
    // all results here
}, function(err) {
    // error here
});
选项1:如果函数存在,请使用该函数的“…Sync”版本 在这种情况下,已经有了
execSync
功能:

选项2:发电机魔术! 出于更广泛的目的,现在您可以使用例如此“生成器”模式来“取消同步”其中的任何异步函数,这对于任何顺序操作系统脚本都非常有用

下面是一个如何在node.js v6+中以同步方式使用
readline
异步函数的示例(我认为也是v4+)

var main=(函数*(){
var rl=require('readline')
.createInterface({输入:process.stdin,输出:process.stdout});
//回调使用迭代器“.next()”恢复“yield”
a=收益率rl.question('您想要这个吗?',r=>main.next(r))
b=收益率rl.question('你确定吗?',r=>main.next(r))
rl.close()
控制台日志(a,b)

})()//更有可能echo命令执行得更快,因为
exec
是一种异步方法。这是一个提示:您需要重新考虑如何设置执行。它们不是按相反顺序执行的,它们是异步的,并且一个不等待另一个。Shell命令由Shell执行,而
exec
只是一个访问它的接口。您可以在终端中运行这些命令中的任何一个
var Promise = require('bluebird');
var execP = Promise.promisify(require('child_process').exec);

var commands = ["npm install", "echo 'hello'"];
Promise.mapSeries(commands, execP).then(function(results) {
    // all results here
}, function(err) {
    // error here
});
var main = (function* () {
  var rl = require('readline')
          .createInterface({input: process.stdin, output: process.stdout });
  // the callback uses the iterator '.next()' to resume the 'yield'
  a = yield rl.question('do you want this? ', r=>main.next(r))  
  b = yield rl.question('are you sure? ', r=>main.next(r))      
  rl.close()
  console.log(a,b)
})()          // <- generator executed, iterator 'main' created
main.next()   // <- start iterator, run till the first 'yield'