我想建立一个使用require('child_process').spawn
生成子进程的承诺。该流程将其输出流式传输到stdout
,将其错误传输到stderr
。
我希望承诺:
reject(child.stderr stream (or its data))
发出任何数据,则child.stderr
。resolve(child.stdout stream)
。我这样做是因为我想将承诺链接到:
then
流的child.stdout
(将流上传到S3存储桶)。catch
,允许我正确处理错误。将promises和流程组合起来是否可行? 我正在考虑在stderr周围工作,但不确定如果有大量数据进入stdout之间发生了什么,而且我没有足够快地处理它。
答案 0 :(得分:1)
正如我所看到的,问题是你不知道在整个过程完成之前是否有stderr
的数据,因为它可以随时放置数据。
因此,在调用resolve()
或reject()
之前,您必须等待整个过程完成。而且,如果您希望将整个数据发送到其中任何一个,则必须缓冲它们。您可以在reject()
获得数据后立即致电stderr
,但不能保证您拥有所有数据,因为它是一个流。
所以,如果你不想缓冲,那么最好让调用者直接看到流。
如果你可以缓冲数据,你可以自己缓冲它:
根据node.js doc中的spawn示例,您可以像这样添加对它的promise支持:
const spawn = require('child_process').spawn;
function runIt(cmd, args) {
return new Promise(function(resolve, reject) {
const ls = spawn(cmd, args);
// Edit thomas.g: My child process generates binary data so I use buffers instead, see my comments inside the code
// Edit thomas.g: let stdoutData = new Buffer(0)
let stdoutData = "";
let stderrData= "";
ls.stdout.on('data', (data) => {
// Edit thomas.g: stdoutData = Buffer.concat([stdoutData, chunk]);
stdoutData += data;
});
ls.stderr.on('data', (data) => {
stderrData += data;
});
ls.on('close', (code) => {
if (stderrData){
reject(stderrData);
} else {
resolve(stdoutData);
}
});
ls.on('error', (err) => {
reject(err);
});
})
}
//usage
runIt('ls', ['-lh', '/usr']).then(function(stdoutData) {
// process stdout data here
}, function(err) {
// process stdError data here or error object (if some other type of error)
});