[英]How can I execute shell commands in sequence?
我有一个我想用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命令? 我发现它对shell的异步处理有点麻烦。
注意:
我知道像shelljs
这样的shelljs
在。 我正在尝试仅使用基本nodejs。
你的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
});
ES6承诺
由于promises已在ES6中标准化并且现在已内置到node.js中,因此我喜欢使用Promises进行异步操作:
var exec = require('child_process').exec;
function execPromise = function(cmd) {
return new Promise(function(resolve, reject) {
exec(cmd, function(err, stdout) {
if (err) return reject(err);
resolve(stdout);
});
});
}
var commands = ["npm install", "echo 'hello'"];
commands.reduce(function(p, cmd) {
return p.then(function(results) {
return execPromise(cmd).then(function(stdout) {
results.push(stdout);
return results;
});
});
}, Promise.resolve([])).then(function(results) {
// all done here, all results in the results array
}, function(err) {
// error 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
});
在这种情况下,已经有一个execSync
函数:
child_process.execSync(命令[,options])
为了更通用的目的,现在您可以使用例如这个“生成器”模式来“解除”其中的任何异步函数 ,这对于任何顺序OS脚本都非常有用。
这里有一个如何在node.js v6 +中以同步方式使用readline
异步函数的例子(我想也是v4 +)
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'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.