26

I am trying to make use of the async/await functionality with regard to aws and dynamo db. Below is an example of how to put an object pre asyn await, as you can see in the callback you have access to data which contains the put object. However in the second block of code which uses async and promise the result is an empty object, any thoughts?

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.03.html

Non Promise Version

var docClient = new AWS.DynamoDB.DocumentClient();

var table = "Movies";

var year = 2015;
var title = "The Big New Movie";

var params = {
    TableName:table,
    Item:{
        "year": year,
        "title": title,
        "info":{
            "plot": "Nothing happens at all.",
            "rating": 0
        }
    }
};

console.log("Adding a new item...");
docClient.put(params, function(err, data) {
    if (err) {
        console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
    } else {
        console.log("Added item:", JSON.stringify(data, null, 2));
    }
});

Promise async Version - assume the wrapping function is marked async

var docClient = new AWS.DynamoDB.DocumentClient();

var table = "Movies";

var year = 2015;
var title = "The Big New Movie";

var params = {
    TableName:table,
    Item:{
        "year": year,
        "title": title,
        "info":{
            "plot": "Nothing happens at all.",
            "rating": 0
        }
    }
};
const result: any = await dynamoDb.put(params).promise()
console.log(result) 
Mingo
  • 836
  • 3
  • 12
  • 19

3 Answers3

16

According to the doc you have to use ReturnValues if you want something back.

Gabriel Bleu
  • 9,703
  • 2
  • 30
  • 43
  • hmm yes that does seem to make sense, weird how the non promise object does seem to return the full object in the callback regardless of whether you have set this value, TBH i dont really need a response but it bugged me the behavior appeared different and wanted to make sure I wasnt missing anything / doing anything silly. Thanks for looking into it, ill mark this as the correct answer – Mingo Mar 14 '19 at 20:48
  • 2
    I found that you can also use `docClient.update` even when creating a new item. `ReturnValues` can then accept a value of `ALL_NEW` which will return what you are looking for. In the case of `docClient.put` you can't use the `ALL_NEW` option for `ReturnValues`. Hopefully this helps anyone else that stumbles across this. – K-Sid Sep 04 '20 at 03:09
8

When you're using promises, you should handle the returned promise object using .then() and .catch(). If you take a look at the documentation, your request should look like this:

dynamoDb.put(params).promise()
  .then(function(data) {
    console.log(data);
  })
  .catch(function(err) {
    console.log(err);
  });

This will also help you see if you are getting any error (same idea as surrounding an await with try/catch, but clearer syntax)

Deiv
  • 3,000
  • 2
  • 18
  • 30
  • presumably clearer syntax is a matter of opinion and shouldn't affect the behavior? No error is being thrown, the object is being created in the database but the response is an empty object rather than the put object – Mingo Mar 14 '19 at 19:15
  • Yupe shouldn't affect behavior, but handling the promise success/error in the correct way is not an opinion. It's successful and the object returned is empty, even when using .then()? That can't be possible... – Deiv Mar 14 '19 at 19:20
  • 2
    According to this https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/ both methods are "corret" ways of handling promise success and error. Anyway i tried it using .then().catch() and behaviour is the same, empty response object, weird – Mingo Mar 14 '19 at 19:35
1

I have tried ReturnValues: 'ALL_OLD' but in async await it has no result.

Here is a part of code:

const answersParams = {
          TableName: ANSWERS_TABLE,
          Item: {
            answersId,
            answers,
            userId,
            quizId,
          },
          ReturnValues: 'ALL_OLD',
        };

        try {
          const createdAnswres = await db.put(answersParams).promise();

          return {
            statusCode: 201,
            body: JSON.stringify(createdAnswres && createdAnswres.Item),
          };
        } catch (error) {
          return {
            statusCode: 500,
            body: 'failed to save user answers',
          };
        }
      }
    

So I had to add another request to db:

const createdAnswres = await db.get({
              TableName: ANSWERS_TABLE,
              Key: { answersId },
            })
            .promise();
    

Aleks Barylo
  • 131
  • 1
  • 2
  • 4