异步等待不适用于功能 - 创建 pdf 文档,然后通过电子邮件发送

Async await not working for function - create pdf document and then email it

const pdf = require('pdfkit')
const QR = require('qrcode')
    
const emailTickets =  async (userEvent, tickets) => {   
    await createQRCodes(tickets)
    await createTicketPDF(tickets, userEvent)
    await sendGridEmail(emailDetails, true)
}   

问题似乎是 async/await 对于 createTicketPDF 函数无法正常工作。

当我 运行 使用上述 emailTickets 函数时,会通过电子邮件发送一个空白的 pdf 文档。然而,当我 运行 它与下面 setTimeOut 时,pdf 包含我想要的所有细节。

const emailTickets =  async (userEvent, tickets) => {   
    await createQRCodes(tickets)
    await createTicketPDF(tickets, userEvent)
    setTimeout(async() => {await sendGridEmail(emailDetails, true)}, 5000);
}   

我更喜欢这样一种解决方案,即代码在调用 sendGridEmail 函数之前等待 createTicketPDF 函数完成。

下面是 createTicketPDF 函数的代码:

const createTicketPDF = async (tickets, userEvent) => {
    const doc = new pdf 
    doc.pipe(fs.createWriteStream(`./tickets/${tickets[0]._id}.pdf`))
    await tickets.map(async(ticket, index)=> {
        return(
            await doc.fontSize(30),
            await doc.text(userEvent.title),
            await doc.fontSize(10),
            await doc.moveDown(),
            await doc.text(`Venue: ${userEvent.venue}, ${userEvent.address1} `),
            await doc.moveDown(),
            await doc.fontSize(20),
            await doc.text(`Ticket ${index+1} of ${tickets.length}: ${ticket.ticketType}`), 
            await doc.image(`./qrCodes/${ticket._id}.png`, {
                align: 'center',
                valign: 'center'
            }),
            await doc.addPage()
        )
    })
    doc.end()   
}

我在这个函数中有一个 forEach 循环,但在得知 forEach 循环不能很好地与 async await 一起工作时用地图替换了它。

我也尝试过使用 (const ticket of tickets){} 但这也不起作用

VS 代码建议地图中 await 的 none 执行任何操作

为了完整起见,下面是 createQRCodes。此功能完美运行。

const createQRCodes = async (tickets) => {
    let CreateQRCodes = tickets.map(ticket => {     
        return(
        QR.toFile(`./qrCodes/${ticket._id}.png`, String([ticket._id, ticket.randomNumber, ticket.creationTime.getTime(), ticket.userEvent]))
        )})
    await Promise.all(CreateQRCodes)
}

我哪里出错了

此处为 Twilio SendGrid 开发人员布道师。

据我从文档中得知,PDFKit 是一个同步库。唯一异步的是将 PDF 写入磁盘。因此,您的代码不需要 await createTicketPDF 函数中的任何内容。不过,您确实需要监听流结束,因此您可以 return 承诺在流结束时解析,如下所示:

const createTicketPDF = (tickets, userEvent) => {
    const doc = new pdf 
    const stream = doc.pipe(fs.createWriteStream(`./tickets/${tickets[0]._id}.pdf`))
    tickets.map((ticket, index)=> {
        return(
            doc.fontSize(30),
            doc.text(userEvent.title),
            doc.fontSize(10),
            doc.moveDown(),
            doc.text(`Venue: ${userEvent.venue}, ${userEvent.address1} `),
            doc.moveDown(),
            doc.fontSize(20),
            doc.text(`Ticket ${index+1} of ${tickets.length}: ${ticket.ticketType}`), 
            doc.image(`./qrCodes/${ticket._id}.png`, {
                align: 'center',
                valign: 'center'
            }),
            doc.addPage()
        )
    })
    doc.end()
    const promise = new Promise((resolve) => {
      stream.on("finish", () => {
        resolve();
      })
    });
    return promise;
}
const emailTickets =  async (userEvent, tickets) => {   
    await createQRCodes(tickets)
    await createTicketPDF(tickets, userEvent)
    await sendGridEmail(emailDetails, true)
}