I am being challenged trying to make an async call inside an event.
Here's the code from Nodemailer - I've added the line where I need to make an async call:
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);
}
});
I found this post which suggest switching things around which makes sense however I have been unable to apply it correctly to this.
Update - The answer was to mock sendMail using Sinon.
You can just mark your callback as async
and use await
inside of it.
The fact that it's an event
handler callback makes no difference since at the end it's just a plain-old 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')
If you still can't get it to work it might be because transporter.on
is not the same as EventEmitter.on
- meaning it's a custom function provided by transporter
.
It could assume internally that the callback function provided is not a Promise
- keep in mind that labelling a function as async
effectively turns it into a Promise
.
If that's the case you might want to wrap the async
function in an 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')
BUT (-- ewewewew -- AIR RAID SIRENS) LOOK AT ME I AM A WARNING DONT MISS ME (AIR RAID SIRENS)
Good. you've seen this.
Make sure you properly wire-up exception handling for EventEmitters. try/catch
does absolutely nothing for them, since their exception handling semantics are entirely different than what you hold to be true for everything else.
Failure to do so is guaranteed to have you debugging production for 2 days at a minimum. Their crashes (used to at least) trigger a god-aweful cascade that results in very weird error stacks.
Anyway read the article, if it goes dead, and long story short you need to have an error
listener attached.