Azamat Abdullaev
Azamat Abdullaev

Reputation: 806

AWS Lambda does not execute the promises without await

I have the following handler for my AWS Lambda function. I don't want to or need to wait for Promise.all resolve or reject. Because, I am not interested about its result. My purpose is to just send those requests and finish. The problem is that if I remove the await keyword (pointed with an arrow), the requests are not firing up. But, if I put the await keyword, the Lambda function needs to run and be charged for 3-5 seconds, and it is not cost effective for me.

Could you explain what I am doing wrong? Why the requests are not being sent without the await keyword?

module.exports.handler = async (event) => {
  try {
    const urls = [/*some API urls*/];
--> await Promise.all(urls.map((url) => {
      return axios.post(url, { email })
        .catch((error) => {
          console.log(error);
        });
    }));

    return {
      statusCode: 200,
      body: JSON.stringify({ message: 'OK' }),
      headers: {
        'Content-Type': 'application/json',
      },
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify({ message: 'INTERNAL_ERROR' }),
      headers: {
        'Content-Type': 'application/json',
      }
    }
  }
};

Upvotes: 8

Views: 5857

Answers (2)

weisk
weisk

Reputation: 2540

if you don't care about the result of all those requests, but you still want to be sure all of them are performed, you don't need to have your lambda as an async function.

did you try doing something like:

module.exports.handler = (event) => {
  const urls = [/*some API urls*/];
  urls.map((url) => axios.post(url, { email })
    .catch((error) => console.log(error));
  return {
    statusCode: 200,
    body: JSON.stringify({ message: 'OK' }),
    headers: {
      'Content-Type': 'application/json',
    },
  };
}

I don't even think you would need your outer try catch since anyway any error happening on the map iterator, you are just swallowing it so it would never propagate up.

Upvotes: 0

derpirscher
derpirscher

Reputation: 17392

As stated in the 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.

If you don't return a promise, there is no guarantee your async tasks will run to an end. With making the handler async you are indeed returning a promise. But without awaiting the Promise.all this promise from the handler is immediately resolved, and thus execution of your lambda (and all unfinished async tasks) is stopped.

And this seems quite logical. Otherwise everybody would write the heavy lifting computations in an async task which runs for a long time. And the only synchronous call in the lambda function would be calling that async task and the lambda function would return after (and be charged for) only a few milliseconds.

If you want to pay only for a 100ms, make your task fast enough. If you task takes 4 seconds, you have to pay for 4 seconds.

Upvotes: 15

Related Questions