承诺解析到子流 stdout 并拒绝子流 stderr [英] Promise resolving to child stream stdout and rejecting child stream stderr

查看:61
本文介绍了承诺解析到子流 stdout 并拒绝子流 stderr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'd like to build a promise that spawns a child process using require('child_process').spawn. The process streams its output to stdout and its errors to stderr.

我希望承诺:

  • reject(child.stderr stream (or its data)) 如果 child.stderr 发出任何数据.
  • resolve(child.stdout stream) 仅当没有发出错误时.
  • reject(child.stderr stream (or its data)) if child.stderr emits any data.
  • resolve(child.stdout stream) only if no error is emitted.

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

I'm doing this because I want to chain the promise to:

  • 处理 child.stdout 流的 then(将流上传到 S3 存储桶).
  • 一个可以处理 child.stderr 流的 catch,让我能够正确处理错误.
  • a then that processes the child.stdout stream (upload the stream to an S3 bucket).
  • a catch that can process the child.stderr stream, allowing me to properly handle errors.

像这样结合 promise 和 process 流是否可行?我正在考虑解决 stderr,但不确定如果有大量数据进入 stdout 并且处理速度不够快,那么在 stdout 之间会发生什么.

Is it feasible to combine promises and process streams like this ? I was thinking of working around stderr but unsure about whats happening in between to stdout if a lot of data is coming into it and I don't process it fast enough.

推荐答案

在我看来,问题是你不知道你是否曾经获得过 stderr 上的数据,直到整个过程结束因为它可以随时将数据放在那里.

As I see it, the issue is that you don't know whether you ever got data on stderr until the entire process is done as it could put data there at any time.

因此,在调用resolve()reject() 之前,您必须等待整个过程完成.而且,如果您随后希望将整个数据发送到其中任何一个,则必须对它们进行缓冲.您可以在获得 stderr 上的数据后立即调用 reject(),但不能保证您拥有所有数据,因为它是一个流.

So, you have to wait for the entire process to be done before calling resolve() or reject(). And, if you then want the entire data to be sent to either one of those, you'd have to buffer them. You could call reject() as soon as you got data on stderr, but you aren't guaranteed to have all the data yet because it's a stream.

因此,如果您不想缓冲,最好让调用者直接看到流.

So, if you don't want to buffer, you're better off just letting the caller see the streams directly.

如果你可以缓冲数据,你可以像这样自己缓冲:

If you are OK with buffering the data, you can buffer it yourself like this:

基于 node.js 文档中的 spawn 示例,您可以像这样添加 promise 支持:

Based on the spawn example in the node.js doc, you could add promise support to it like this:

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

这篇关于承诺解析到子流 stdout 并拒绝子流 stderr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆