Moose
Moose

Reputation: 1241

Node Lambda returns null for AWS console

The following code works great locally, but after deploying it to AWS Lambda and running it my records are not saving to DynamoDB and I'm getting a return of null from Lambda.

I know it's not a permissions issue with the Lambda execution role because I can successfully insert one individual record into DynamoDB from the AWS console.

I think the issue has to do with the .forEach loop and how the aws-sdk works. I'm not sure I'm completely wrapping my head around how to properly use JavaScript promises with Lambda. Any help is greatly appreciated!

module.exports.handler = async event => {

  const getItems = () => {... // return items //...}

  const addToDb = (items) => {
    
    items.forEach(item => {

      var params = {
          Item: {"id": {S: item.id}, "title": {S: item.title}}, 
          ReturnConsumedCapacity: "TOTAL",
          TableName: "my-table"
      };

      dynamodb.putItem(params, (err, data) => {
        if (err) console.log(err, err.stack);
        else     console.log(data);
      });

    });
    
  };

  const getItemsPromise = new Promise((resolve) => {
    const items = getItems();
    const itemsAddedToDb = addToDb(items);
    resolve(itemsAddedToDb);
  });

  return getItemsPromise
    .catch(err => console.log(err));
};

Upvotes: 0

Views: 318

Answers (1)

Ranjeet Eppakayala
Ranjeet Eppakayala

Reputation: 3028

This should work!

exports.handler = (event) => {
  const getItems = () => {...} // assuming getItems returns promise

  const addToDb = (items) => {
    asyncForEach(items, async (item) => {
      const params = {
        Item: {
          id: {
            S: item.id
          },
          title: {
            S: item.title
          }
        },
        ReturnConsumedCapacity: 'TOTAL',
        TableName: 'my-table'
      }

      await dynamodb.putItem(params, (err, data) => {
        if (err) console.log(err, err.stack)
        else console.log(data)
      })
    })
  }

  const getItemsPromise = new Promise(async (resolve) => { // rule eslintno-async-promise-executor - use then instead
    const items = await getItems()
    const itemsAddedToDb = await addToDb(items)
    resolve(itemsAddedToDb)
  })

  const asyncForEach = async (array, callback) => {
    for (let index = 0; index < array.length; index++) {
      await callback(array[index], index, array)
    }
  }

  return getItemsPromise.catch((err) => console.log(err))
}

Notice:

async for export.handler has no use. use async only if function has await inside it.

async await doesn't support for forEach try for loop instead

Upvotes: 1

Related Questions