Julio Claret
Julio Claret

Reputation: 23

Node.js Promise within event handler is not executing

I'm not able to executive a promise within this event handler. The promise returns fine outside the handler. Then the same code doesn't run inside the handler.

'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!';
};

The output is:

INFO    resolved after 2 seconds
INFO    an event occurred!

Inside the event handler, we get the first log, but not the log from within or after resolveAfter2Seconds().

Upvotes: 1

Views: 366

Answers (1)

Manuel Spigolon
Manuel Spigolon

Reputation: 12870

As written in aws docs:

If your code performs an asynchronous task, return a promise to make sure that it finishes running. When you resolve or reject the promise, Lambda sends the response or error to the invoker.

So this is happening:

    // 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

To solve you need to use the callback interface since the docs say:

For non-async handlers, function execution continues until the event loop is empty or the function times out.

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

Or you should change your event emitter to a simple function that you can await:

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!'
}

Upvotes: 1

Related Questions