Async/await 函数在创建写入流后不等待

Async/await function not awaiting after creating write stream

我有一个节点应用程序,它使用 express 进行路由,使用 pdfmake npm 生成 pdf 文档。单击一个按钮,我发出一个 http 请求,从数据库中检索数据,生成一个 pdf 文档,然后保存到磁盘。但是,我的 async/await 函数似乎只在我使用 fs.createWriteStream(path) 创建写入流之前起作用。之后的所有 async/await 似乎都被忽略了。此外,这只发生在生产服务器上。在本地调试我的应用程序时,ALL async/await 函数似乎有效。关于为什么会发生这种情况有什么想法吗?

快递路线:

router.patch('/:id(\d+)/approve', async function (req, res) {
    try {
        let id = req.params.id

        const invoice = await db.fetchInvoiceById(id)

        const harvestInvoice = await harvest.getInvoiceById(invoice.harvest_id)

        // generate invoice pdf
        await pdf.generateInvoice(invoice, harvestInvoice)

        res.status(200).json({ id: id })
    } catch (error) {
        res.status(400).json({ error: 'something went wrong' })
    }
})

函数:

async function SLEEP5() {
  await new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('DONE');
    }, 5000);
  });
}

function test(doc, invoicePath) {
  return new Promise((resolve, reject) => {
    const writeStream = fs.createWriteStream(invoicePath)

    writeStream.on("finish", () => { resolve(true) })
    writeStream.on("error", () => { reject(false) })

    doc.pipe(writeStream)
    doc.end()
  })
}

exports.generateInvoice = async function generateInvoice(invoice, harvestInvoice) {
    const invoicePath = `${__dirname}\invoice_${invoice.number}.pdf`

    let printer = new PdfPrinter(fonts)
    let def = { // pdf defined here }

    // generate invoice PDF
    let doc = printer.createPdfKitDocument(def, {})

    await SLEEP5() // THIS IS AWAITED

    await test(doc, invoicePath)

    await SLEEP5() // THIS IS NOT AWAITED FOR SOME REASON
}

我在 aws ec2 服务器上使用 PM2 运行 这个节点应用程序,我使用 pdfmake

版本 0.2.4

我不知道 printer.createPdfKitDocument(def, {}) 到底做了什么,但是

let doc = printer.createPdfKitDocument(def, {})
await sleep(5)
await writeStreamToFile(doc, invoicePath)

确实看起来有问题。如果 doc 在创建时没有暂停,它可能会 运行 并在您还在睡觉时完成 ,然后将任何内容通过管道传输到您的写入流中,这将永远不会发出finisherror 事件。所以删除 await sleep(5),然后 立即 执行 doc.pipe(writeStream) 并且 立即 开始监听事件。

如果你坚持要等,要么

let doc = printer.createPdfKitDocument(def, {})
await Promise.all([
  sleep(5),
  writeStreamToFile(doc, invoicePath),
])

或尝试

const doc = printer.createPdfKitDocument(def, {})
doc.pause()
await sleep(5)
await writeStreamToFile(doc, invoicePath)

(另一种解释当然是 createPdfKitDocument 创建了一个 never-ending 流,或者在没有发出 error 事件的情况下发生错误,等等,这将导致 promise 不被执行已解决)。

我明白我的问题是什么了。事实证明,我正在使用 pm2 start appName --watch to 运行 我的应用程序。我正在将 pdf 写入应用程序中的目录。 PM2 在写入 pdf 时检测到变化并会重新启动应用程序(因为 --watch 标志),导致我看到的所有问题。