将 NodeJS 子进程标准输出发送到 Express 响应对象

问题描述

我目前将子进程的标准输出通过管道传输到 (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 永远不会完成,而是一直等待其标准输出。)

解决方法

看起来 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();