承诺解析子流标准输出并拒绝子流stderr

时间:2016-03-09 15:36:41

标签: node.js process stream promise spawn

我想建立一个使用require('child_process').spawn生成子进程的承诺。该流程将其输出流式传输到stdout,将其错误传输到stderr

我希望承诺:

    如果reject(child.stderr stream (or its data))发出任何数据,则
  • child.stderr
  • 仅当没有发出错误时,
  • resolve(child.stdout stream)

我这样做是因为我想将承诺链接到:

  • 处理then流的child.stdout(将流上传到S3存储桶)。
  • 可以处理child.stderr流的catch,允许我正确处理错误。

将promises和流程组合起来是否可行? 我正在考虑在stderr周围工作,但不确定如果有大量数据进入stdout之间发生了什么,而且我没有足够快地处理它。

1 个答案:

答案 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)
});