在事件发射器中使用异步

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.onEventEmitter.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);