我现在正在node.js中尝试这样的事情:
var exec = require('child_process').exec
var write = require('fs-writefile-promise')
function run() {
var myArray = [];
var execs = [];
for (var i = 1; i <= 7; i++) {
(function(cntr) {
write('file-' + i + '.txt', someString)
.then(function (filename) {
execs.push(new Promise(function(resolve, reject) {
exec('cat ' + 'file-' + cntr + '.cnf', function(error, stdout, stderr) {
console.log(cntr + ' ' + stdout);
if (stdout.search(/\bsomeString\b/) > -1) {
myArray.push(cntr);
resolve();
}
else {
resolve();
}
})
}))
})
.catch(function (err) {
console.error(err);
});
})(i);
}
return Promise.all(execs).then(function() {
return new Promise(function(resolve) {
resolve(myArray);
})
})
}
run().then(function(result) {
console.log(result);
});
正如您所看到的,我正在创建多个运行exec()
的Promise,并且每个Promise在exec()
完成时解析。
然后我等待每个Promise在Promise.all(execs)
中解决以返回myArray
作为承诺。然而,当我在最后执行我的run()
函数时,它返回一个空数组。我想这与Promise.all()
有关,因为即使execs
中的某些Promise尚未解决,它也会解决,但我不确定,这就是为什么我真的需要一些帮助。有谁知道我在代码中犯了什么错误?
非常感谢你!
#EDIT 1
var exec = require('child_process').exec
var write = require('fs-writefile-promise')
function run() {
var myArray = [];
var execs = [];
for (var i = 1; i <= 7; i++) {
(function(cntr) {
return new Promise(function(resolve, reject) {
fs.writeFile('file-' + i + '.txt', someString, (err) => {
if (err) {
reject();
}
else {
resolve();
}
});
})
.then(function (filename) {
execs.push(new Promise(function(resolve, reject) {
exec('cat ' + 'file-' + cntr + '.cnf', function(error, stdout, stderr) {
console.log(cntr + ' ' + stdout);
if (stdout.search(/\bsomeString\b/) > -1) {
myArray.push(cntr);
resolve();
}
else {
resolve();
}
})
}))
})
.catch(function (err) {
console.error(err);
});
})(i);
}
return Promise.all(execs).then(function() {
return new Promise(function(resolve) {
resolve(myArray);
})
})
}
run().then(function(result) {
console.log(result);
});
答案 0 :(得分:2)
您的尝试都有很多问题。第一次尝试的问题是你在异步操作之后填充了execs数组,所以当你实际将数组传递给Promise.all()
时它没有任何内容,因此Promise.all()
没有什么可以等待的。
此外,您不仅仅使用已经创建的承诺,因此您最终会获得比所需更多的承诺。
一般情况下,最好在主逻辑之外“实现”异步操作,然后让所有逻辑成为承诺驱动,而不是将承诺与普通回调混合和匹配。这是一个试图解决这些问题的版本:
var exec = require('child_process').exec
var write = require('fs-writefile-promise')
// make promisified version of exec
function execP(file, options) {
return new Promise(function(resolve, reject) {
exec(file, options, function(err, stdout, stderr) {
if (err) return resolve(err);
resolve({stdout: stdout, stderr: stderr});
});
});
}
function run() {
var promises = [];
for (var i = 1; i <= 7; i++) {
promises.push(write('file-' + i + '.txt', someString).then(function(filename) {
return execP(filename);
}));
}
return Promise.all(promises).then(function(results) {
// results is an array of {stdout: xxx, stderr: yyy} objects
// process those results into a new array of just indexes
var final = [];
results.forEach(function(data, index) {
if (data.stdout.search(/\bsomeString\b/) > -1) {
final.push(index);
}
});
return final;
});
}
run().then(function(results) {
// array of indexes that contained the desired search string
}, function(err) {
// process error here
});
注意:这会并行运行您的所有exec操作,这是您的原始代码所做的操作。如果你想按顺序运行它们,也可以这样做,但需要进行一些调整。
答案 1 :(得分:1)
由于write
是异步的,所以此阶段的程序将返回主线程,直接进入你的promise.all并在加载execs之前返回。
我建议你创建一个函数,它返回的承诺文件保存后跟exec。