在没有回调的情况下使用 Node.js 流

Working with Node.js streams without callbacks

要从 Node.js 服务器向客户端发送 PDF 文件,我使用以下代码:

const pdf = printer.createPdfKitDocument(docDefinition);

const chunks = [];

pdf.on("data", (chunk) => {
    chunks.push(chunk);
});

pdf.on("end", () => {
    const pdfBuffered = `data:application/pdf;base64, ${Buffer.concat(chunks).toString("base64")}`;
    res.setHeader("Content-Type", "application/pdf");
    res.setHeader("Content-Length", pdfBuffered.length);
    res.send(pdfBuffered);
});

pdf.end();

一切正常,唯一的问题是这里的流使用回调方法而不是 async/await

我找到了 :

const { pipeline } = require("stream/promises");

async function run() {
    await pipeline(
        fs.createReadStream('archive.tar'),
        zlib.createGzip(),
        fs.createWriteStream('archive.tar.gz')
    );

    console.log('Pipeline succeeded.');
}

run().catch(console.error);

但我不知道如何将初始代码采用 stream/promises

如果回调只执行一次,则只能将回调-API转换为async/await

您在网上找到的那个有效,因为您只是在等待整个流完成,然后回调运行一次。您得到的是对每个传入数据块执行多次的回调。

您可以查看其他资源来使流更易于使用,例如 RXJS, or this 即将推出的 ECMAScript 提议,将可观察对象添加到该语言中。这两个都是为了处理回调可以执行多次的场景——这是 async/await 做不到的。

您可以手动将 PDF 代码包装在这样的承诺中,然后将其用作 returns 承诺的函数:

function sendPDF(docDefinition) {
    return new Promise((resolve, reject) => {
        const pdf = printer.createPdfKitDocument(docDefinition);

        const chunks = [];

        pdf.on("data", (chunk) => {
            chunks.push(chunk);
        });

        pdf.on("end", () => {
            const pdfBuffered =
                `data:application/pdf;base64, ${Buffer.concat(chunks).toString("base64")}`;
            resolve(pdfBuffered);
        });

        pdf.on("error", reject);

        pdf.end();
    });
}

sendPDF(docDefinition).then(pdfBuffer => {
    res.setHeader("Content-Type", "application/pdf");
    res.setHeader("Content-Length", pdfBuffer.length);
    res.send(pdfBuffer);
}).catch(err => {
    console.log(err);
    res.sendStatus(500);
});

因为有很多 data 事件,你不能只承诺数据部分。您仍然需要监听每个 data 事件并收集数据。