事件处理程序中的Node.js Promise没有执行

问题描述

我无法在此事件处理程序中执行承诺。在处理程序之外,promise返回正常。然后,相同的代码不会在处理程序中运行。

'use strict';
const EventEmitter = require('events');

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved after 2 seconds');
    },2000);
  });
}

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event',async () => {
    console.log('an event occurred!');
    const result = await resolveAfter2Seconds();
    console.log(result);
});

exports.handler = async (event) => {

    const result = await resolveAfter2Seconds();
    console.log(result);

    myEmitter.emit('event');

    return 'Hello from Lambda!';
};

输出为:

INFO    resolved after 2 seconds
INFO    an event occurred!

在事件处理程序内部,我们获得第一个日志,但没有从resolveAfter2Seconds()内或之后的日志。

解决方法

aws docs所述:

如果您的代码执行异步任务,请返回一个承诺以确保其完成运行。当您解决或拒绝承诺时,Lambda会将响应或错误发送给调用方。

这正在发生:

    // this is run since it is part of the promise chain
    const result = await resolveAfter2Seconds(); 
    console.log(result);

    myEmitter.emit('event'); // this starts the timeout but it is not waited
    return 'Hello from Lambda!'; // the lambda exits and resolve

要解决此问题,您需要使用callback界面,因为文档会说:

对于非异步处理程序,函数将继续执行,直到事件循环为空或函数超时为止。

exports.handler = (event,context,callback) => {
  resolveAfter2Seconds()
    .then(result => {
      console.log(result)
      myEmitter.emit('event')
    })
    .then(() => { callback(null,'Hello from Lambda!') })
    .catch(callback)
}

或者您应该将事件发射器更改为可以等待的简单函数:

async function dosomething () {
  console.log('an event occurred!')
  const result = await resolveAfter2Seconds()
  console.log(result)
}

exports.handler = async (event) => {
  const result = await resolveAfter2Seconds()
  console.log(result)
  await dosomething()
  return 'Hello from Lambda!'
}