繁体   English   中英

异步/等待 function 创建写入后不等待 stream

[英]Async/await function not awaiting after creating write stream

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

快递路线:

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
}

我正在使用 PM2 在 aws ec2 服务器上运行此节点应用程序,我使用的是0.2.4版的 pdfmake

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

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

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

当然看起来有问题。 如果doc在创建时没有暂停,它可能会在您还在睡觉时运行并完成,然后 pipe 没有任何内容写入您的 write stream ,它永远不会发出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创建了一个永无止境的 stream,或者没有发出error事件的错误,等等,这将导致 promise 无法解决)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM