过早关闭管道,但如果使用管道则不会

Premature close with pipeline, but not if using pipe

这是一个我无法解决的问题。

这个有效:

let readStream = fs.createReadStream(imgPath);
let imageMagicStream = spawn('convert', ['-', '-resize', '750', '-'], { env: env });
let writeStream = fs.createWriteStream(out);

readStream.pipe(imageMagicStream.stdin);
imageMagicStream.stdout.pipe(writeStream);

但是,如果我尝试改用管道,我会得到 'Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close':

let readStream = fs.createReadStream(imgPath);
let imageMagicStream = spawn('convert', ['-', '-resize', '750', '-'], { env: env });
let writeStream = fs.createWriteStream(out);

pipeline(readStream, imageMagicStream.stdin, writeStream, err => {
    if (err) {
        console.log(err);
    }
});

writeStream 似乎提前关闭了。为什么会发生这种情况,我该如何解决?

跟进答案:

感谢 Bergi 的回答。我找到了一个包 (npm i duplexer),可以让你轻松创建双工流。我的代码现在看起来像这样:

const { pipeline } = require("stream");
const duplexer = require('duplexer');

async function resizeImg(imgPath, out) {
    return new Promise(async (resolve, reject) => {

        let readStream = fs.createReadStream(imgPath);
        let imageMagicStream = spawn('magick', ['convert', '-', '-resize', '750', '-'], { env: env });
        let writeStream = fs.createWriteStream(out);

        let duplexStreams = duplexer(imageMagicStream.stdin, imageMagicStream.stdout);

        await pipeline(readStream, duplexStreams, writeStream, err => {
            if (err) {
                console.log(err);
                return reject(err);
            }
        });

        return resolve();
    });
}

pipeline function 需要一个 转换流 作为中间参数,一个可写可读的流。请注意,您的原始代码进行了 两次 .pipe() 调用,一次调用 stdin,一次调用 stdout,但您的第二个代码片段仅使用 stdin。你必须写

function logError(err) {
    if (err) {
        console.log(err);
    }
}
pipeline(readStream, imageMagicStream.stdin, logError);
pipeline(imageMagicStream.stdout, writeStream, logErrr);

您也可以从子进程的 stdinstdout 构造一个双工流,但这似乎不必要地复杂。