【问题标题】:Send NodeJS child process stdout to Express response object将 NodeJS 子进程标准输出发送到 Express 响应对象
【发布时间】:2021-07-14 15:15:12
【问题描述】:

我目前将子进程的标准输出通过管道传输到(Express)response 对象,如下所示:

try{
    let proc = spawn(exe, args);
    proc.stdout.pipe(response);
    let exitCode = await ending.completion(proc);
}
finally {
    // my own clean up goes here (e.g. releasing locks)
}

ending.completion 定义为

async function(process){
    return new Promise(function(resolve,reject){
        let done = false;
        process.on('exit', (code, signal)=>{
            if(!done){
                done = true;
                if(code !== null){
                    resolve(code);
                } else {
                    reject(signal);
                }
            }
        });
        process.on('error', (err)=>{
            if(!done){
                done = true;
                reject(err);
            }
        });
    });
};

这通常工作正常,除了 proc 在完成/返回之前在内部做了很多等待(在下载/传输时)。我更愿意让它将其输出转储到缓冲区中,然后随着下载的进行,该缓冲区会流入响应对象。如何引入这样的缓冲区?

(第二个(我认为是相关的)问题是,如果客户端中止下载,proc 永远不会完成,而是一直在其标准输出上等待。)

【问题讨论】:

    标签: node.js express es6-promise node-streams


    【解决方案1】:

    看起来 exec method 完全符合您的需要。

    生成一个shell,然后在该shell中执行命令,缓冲 任何生成的输出。

    用它代替spawn。请注意,与spawn 不同,exec 需要将整个命令(带有所有参数)作为单个字符串。以下是官方文档中的示例:

    const util = require('util');
    const exec = util.promisify(require('child_process').exec);
    
    async function lsExample() {
      const { stdout, stderr } = await exec('ls');
      console.log('stdout:', stdout);
      console.error('stderr:', stderr);
    }
    lsExample();
    

    【讨论】:

    • exec 的两个问题是 (1) 输出大小是有限的(至少在默认情况下 -- 将检查最大值)并且我需要 100 的 MB,以及 (2) 数据传输将仅在过程完成并且输出完全缓冲后开始。我宁愿在数据可用时立即开始数据传输。
    • 他希望输出从子进程流式传输到请求中,因此内存占用保持较小。
    猜你喜欢
    • 1970-01-01
    • 2019-05-22
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 2015-08-30
    • 2011-08-29
    • 2010-11-23
    相关资源
    最近更新 更多