How to make async functions work in Lambda?

I have a problem understanding async await in Functions, I believe.

I want my function to return list of datasets from BigQuery. It somehow works on local server, but does not when deployed to Netlify.

Here is the function code:

require('./credentials.json')

// Import the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');
const options = {
    // keyFilename: './src/functions/list_datasets/credentials.json',
    keyFilename: './functions/list_datasets/credentials.json',
    projectId: 'ng-test',
  };
const bigquery = new BigQuery(options);

async function listDatasets() {
  var list = []
  // Lists all datasets in the specified project
  const [datasets] = await bigquery.getDatasets();
  console.log('Datasets:');
  datasets.forEach(dataset => {
      list.push(dataset.id)
      console.log(dataset.id)
  });
  return list
}

exports.handler = async function(event, context) {
    console.log("Returned datasets:", listDatasets())

    return {
      statusCode: 200,
      body: "OK"
    }
}

Result when using netlify dev local server:

Returned datasets: Promise { <pending> }
Response with status 200 in 267 ms.
Datasets:
my_new_dataset
my_new_dataset2
my_new_dataset3
test

Result when using deployed code: (netlify deploy --prod)

12:13:55 PM: 2020-12-17T11:13:55.372Z	c41484c7-0505-4b57-9780-e4ef6df97044	INFO	Returned datasets: Promise { <pending> }
12:13:55 PM: Duration: 7.98 ms	Memory Usage: 79 MB	Init Duration: 278.34 ms

As you can see, it looks like all console logs within async function did not fire.
Also, I don’t know how to wait for Promise so function returns only after receiving data from getDatasets() and actually sending it to user as body. Right now function returns right away and value of function is Promise { <pending> }

It’s been 3 days already, I’m completely stuck. I’d be grateful for some pointers and tips.

Hey @patrykkalinowski :wave:t2:

Welcome to The Community :slight_smile:

I think you’re looking for the await keyword. If you change

console.log("Returned datasets:", listDatasets())

to something like

const sets = await listDatasets()
console.log("Returned datasets:", sets)

That ought to work. I recommend doing some learning around how the Javascript event loop and call stack work; when you initially call out to run an async function (without await), that code doesn’t run the way you might expect. Especially on AWS Lambda (which is what Netlify Functions operate on top of), where the execution context ends immediately at the end of the handler function (no event still on the call stack at that point will be processed – this behavior is not replicated locally in Netlify Dev, which can lead to these mishaps).

I hope that helps!


Jon

1 Like

For others that may find this thread in the future, this other thread may also be useful, going into why / how async calls don’t get processed on Lambda :+1:t2:

https://answers.netlify.com/t/send-response-before-stopping-function/5016/

Thank you @jonsully, everything worked right away :slight_smile:

1 Like