在事件发射器中使用async

时间:2017-11-23 05:59:44

标签: node.js asynchronous eventemitter

我正在尝试在事件中进行异步调用。

以下是来自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);
    }
});

我发现这个post建议切换周围的事情,但是我无法正确地应用它。

更新 - 答案是使用Sinon模拟sendMail。

2 个答案:

答案 0 :(得分:4)

您可以将回调标记为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会有效地将其转换为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')

答案 1 :(得分:0)

我也有类似的情况,如果我是你,我会做以下事情。

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