我在请求中获得了一个字符串数组。 每个字符串都包含要在本机shell上执行的命令。
var process = require('child_process');
function execCommand(req,res,callback){
var params = req.params.list //list is an array in the request
var result = '';
var command = '';
for (var i = 0; i < params.length; i++) {
command = params[i];
cmd = process.exec(command);
cmd.stdout.on('data', function(data){
//push the shell output in variable result
});
cmd.on('close', function(code) {
//convert the variable result to a valid JSON
});
}
res.send(result);
};
所有命令的结果在result
变量中混淆了。如何使for
循环中的函数调用同步?
答案 0 :(得分:5)
使用execSync而不是exec!
for (var i = 0; i < params.length; i++) {
command = params[i];
result += process.execSync(command).toString();
}
正如其他人所指出的,这可能不是一个好主意,因为它会阻止事件循环和正在进行的任何请求。如果正在执行的流程需要很短的时间才能完成,这是可以接受的,但不是这样。
这是一个控制for循环中异步函数流的简单模式...每次进程返回时,params_finished
递增1。一旦完成的进程数等于响应发送的进程总数。
for (var i = 0, total_params=params.length, params_finished=0; i < total_params; i++) {
command = params[i];
cmd = process.exec(command);
cmd.stdout.on('data', function(data){
//push the shell output in variable result
});
cmd.on('close', function(code) {
//convert the variable result to a valid JSON
params_finished++
if(params_finished == total_params){
res.send(result);
}
});
}
答案 1 :(得分:2)
您可以使用execSync
或...
您需要添加控制流程库以帮助进行异步调用,因此您可以选择以串行或并行方式运行您的功能:
Q.nfcall
)https://www.npmjs.com/package/q 答案 2 :(得分:0)
另一种方法是使用等效于循环内的sleep
函数。如果你知道循环的每个实例需要多长时间。
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function myLoopFunction(){
// any code before loop
for (var i = 0; i < params.length; i++) {
// do whatever
await sleep(3000); // 3000 milisecond, for instance
}
};
有关此方法如何运作的完整说明,请参阅this answer。
答案 3 :(得分:0)
将此功能用于 in serie synchronous for loop
function eachSeries(array, fn) {
return new Promise(function (resolveGlobal, rejectGlobal) {
var promises = []
var next = 0
fn(array[next], resolveObj, rejectObj)
function resolveObj(data) {
promises.push( Promise.resolve(data) )
next++
if (next >= array.length) {
Promise.all(promises).then(function (data) {
resolveGlobal(data)
}).catch(function (error) {
rejectGlobal(error)
})
} else {
fn(array[next], resolveObj, rejectObj)
}
}
function rejectObj(error) {
return rejectGlobal(error)
}
})
}
你使用这样的功能......
var process = require('child_process');
function execCommand(req,res,callback){
var params = req.params.list //list is an array in the request
var result = []
eachSeries(params, function (param, resolve, reject) {
cmd = process.exec(param)
cmd.stdout.on('data', function (data){
//... after long time you get data, then
result.push(data.toObject())
resolve()
})
cmd.on("error", function (error){
reject(error) //If something bad happend
})
})
.then(function () {
console.log("All process executed one by one and pushed...")
res.send(result)
})
.catch(function (error) {
console.log("SOmething broke", error)
res.send(error)
})
}
或者如果您愿意
var process = require('child_process');
function execCommand(req,res,callback){
var params = req.params.list //list is an array in the request
eachSeries(params, function (param, resolve, reject) {
cmd = process.exec(param)
cmd.stdout.on('data', function (data){
//... after long time you get data, then
resolve(data.toObject())
})
cmd.on("error", function (error){
reject(error) //If something bad happend
})
})
.then(function (alldata) {
res.send(alldata)
})
.catch(function (error) {
res.send(error)
})
}