在事件发射器中使用异步
Using async in event emitter
我在尝试在事件中进行异步调用时遇到了挑战。
这是来自 Nodemailer 的代码 - 我添加了需要进行异步调用的行:
let transporter = nodemailer.createTransport({
SES: new aws.SES({
apiVersion: '2010-12-01'
}),
sendingRate: 1 // max 1 messages/second
});
// Push next messages to Nodemailer
transporter.on('idle', () => {
while (transporter.isIdle()) {
// I need to make an async db call to get the next email in queue
const mail = await getNextFromQueue()
transporter.sendMail(mail);
}
});
我发现了这个 ,它建议转换一些有意义的东西,但是我一直无法正确地应用它。
更新 - 答案是使用 Sinon 模拟 sendMail。
您可以将回调标记为 async
并在其中使用 await
。
它是一个 event
处理程序回调这一事实没有任何区别,因为最后它只是一个普通的 Function
.
节点片段
'use strict'
const EventEmitter = require('events')
const myEmitter = new EventEmitter()
const getDogs = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve(['Woof', 'Woof', 'Woof'])
}, 500)
})
}
myEmitter.on('event', async () => {
const dogs = await getDogs()
console.log(dogs)
})
myEmitter.emit('event')
替代方案
如果您仍然无法使用它,可能是因为 transporter.on
与 EventEmitter.on
不同 - 这意味着它是由 transporter
提供的自定义函数。
它可以在内部假设提供的回调函数不是 Promise
- 请记住,将函数标记为 async
会强制函数始终隐式地 return a Promise
.
如果是这种情况,您可能希望将 async
函数包装在 IIFE.
中
// ..rest of code from above
myEmitter.on('event', () => {
// wrap into an IIFE to make sure that the callback
// itself is not transformed into a Promise
(async function() {
const dogs = await getDogs()
console.log(dogs)
})()
})
myEmitter.emit('event')
我遇到过类似的情况,如果我是你,我会做以下事情。
let transporter = nodemailer.createTransport({
SES: new aws.SES({
apiVersion: '2010-12-01'
}),
sendingRate: 1 // max 1 messages/second
});
const sendMail = async () => {
while (transporter.isIdle()) {
// I need to make an async db call to get the next email in queue
const mail = await getNextFromQueue()
transporter.sendMail(mail);
}
}
// Push next messages to Nodemailer
transporter.on('idle', sendMail);
我在尝试在事件中进行异步调用时遇到了挑战。
这是来自 Nodemailer 的代码 - 我添加了需要进行异步调用的行:
let transporter = nodemailer.createTransport({
SES: new aws.SES({
apiVersion: '2010-12-01'
}),
sendingRate: 1 // max 1 messages/second
});
// Push next messages to Nodemailer
transporter.on('idle', () => {
while (transporter.isIdle()) {
// I need to make an async db call to get the next email in queue
const mail = await getNextFromQueue()
transporter.sendMail(mail);
}
});
我发现了这个
更新 - 答案是使用 Sinon 模拟 sendMail。
您可以将回调标记为 async
并在其中使用 await
。
它是一个 event
处理程序回调这一事实没有任何区别,因为最后它只是一个普通的 Function
.
节点片段
'use strict'
const EventEmitter = require('events')
const myEmitter = new EventEmitter()
const getDogs = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve(['Woof', 'Woof', 'Woof'])
}, 500)
})
}
myEmitter.on('event', async () => {
const dogs = await getDogs()
console.log(dogs)
})
myEmitter.emit('event')
替代方案
如果您仍然无法使用它,可能是因为 transporter.on
与 EventEmitter.on
不同 - 这意味着它是由 transporter
提供的自定义函数。
它可以在内部假设提供的回调函数不是 Promise
- 请记住,将函数标记为 async
会强制函数始终隐式地 return a Promise
.
如果是这种情况,您可能希望将 async
函数包装在 IIFE.
// ..rest of code from above
myEmitter.on('event', () => {
// wrap into an IIFE to make sure that the callback
// itself is not transformed into a Promise
(async function() {
const dogs = await getDogs()
console.log(dogs)
})()
})
myEmitter.emit('event')
我遇到过类似的情况,如果我是你,我会做以下事情。
let transporter = nodemailer.createTransport({
SES: new aws.SES({
apiVersion: '2010-12-01'
}),
sendingRate: 1 // max 1 messages/second
});
const sendMail = async () => {
while (transporter.isIdle()) {
// I need to make an async db call to get the next email in queue
const mail = await getNextFromQueue()
transporter.sendMail(mail);
}
}
// Push next messages to Nodemailer
transporter.on('idle', sendMail);