异步等待不适用于功能 - 创建 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)
}
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)
}