2

this seems like a very simple operation and I'm sure I will kick myself when it is solved!

This function retrieves a date from a Dynamodb database from AWS Lambda running Node.js 6.10. Its called elsewhere as

var lastLogin = getLastLogin(UserId);

Looking at the console it is successfully retrieving the date and i get "obj is 2018-04-08" but I just cant seem to pass the "obj" string into the lastLogin variable.

function getLastLogin(UserId) {  
var docClient = new AWS.DynamoDB.DocumentClient();
var table = "REMOVED-FOR-PRIVACY";
var params = {
TableName:table,
Key:{
    "UserId": UserId,
}
};
console.log("Getting last login...");    
docClient.get(params, ((err, data) => {
if (err) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
} else {
var payload = JSON.stringify(data, null, 2);
console.log ('payload content = ' + payload);
if (payload == '{}') {
console.log ('found nothing');
} else {
obj = JSON.parse (payload).Item.lastLogin;
obj = JSON.stringify(obj);
console.log ("obj is " + obj); // obj is 2018-04-08 
}}
return obj; }));
console.log("Returned date is " + obj); // Returned date is undefined
};

2 Answers 2

3

First, you have a couple of issues in your code: You're referencing obj from outside its scope which would naturally result in undefined plus you're enclosing the callback (arrow function) for get in extra parenthesis.

However, that's not your main problem. The get method is an asynchronous call that uses a callback interface. So, your function exits before get returns any result.

You could try using either a callback or a 'thenable' promise. For example:

function getLastLogin(userId) {
  const docClient = new AWS.DynamoDB.DocumentClient();
  const params = {
    TableName: "TABLE_NAME",
    Key: {
      "UserId": userId
    }
  };

  return docClient.get(params).promise();
}

let lastLogin;
getLastLogin(userId)
  .then((data) => {
    if (!data.Item || !data.Item.lastLogin) {
      console.log("User not found.");
    } else {
      lastLogin = data.Item.lastLogin;
      console.log("Last login: " + lastLogin);
    }
  })
  .catch((err) => {
    console.log(err);
  });
Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant, thank you! Beginner coder so had no idea how about this but that makes perfect sense!
1

You're making a call to the database which is always asynchronous. DynamoDB passes a callback function to the end of the .get method which it invokes when the result comes back, thus the value is passed in to the closure where you're logging it. However the code continues to run outside of that function without waiting for it. This solution uses promises like the implementation above, but written slightly differently where we return the value to a new variable called 'result' once it's successfully resolved. Rewritten using ES6 syntax.

const getLastLogin = UserId => {  
  const docClient = new AWS.DynamoDB.DocumentClient();
  const table = "REMOVED-FOR-PRIVACY";
  const params = {
    TableName:table,
    Key: {
      "UserId": UserId,
    }
  } ​
​
const result = new Promise((resolve, reject) => docClient.get(params, ((err, data) => {
 ​if (err) {
   ​console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
   reject(err);
 ​} 
 ​if (data) {
   ​resolve(data);
 ​}
})));

return result;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.