I have the following function definition. Essentially, what it does is query a DynamoDB table and return the deviceID of the corresponding partition key.
GetDeviceIdFromHash: function (id) {
const params = {
TableName: process.env.USER_TABLE,
Key: {
id: id
}
};
dynamoDb.get(params, function(error, result) {
// handle potential errors
if (error) {
console.log(error);
return "";
}
return result;
});
}
The problem is that this function ALWAYS returns undefined, irrespectively of whether or not the id attribute is present in the database.
I am not entirely sure as to why this is happening.
Based on my hunch, I'm thinking that this might be related to dynamoDb.get() being an async statement, but my experience with node.js is limited so I don't know how to proceed.
Caller to the function:
'use strict';
const AWS = require('aws-sdk'); // eslint-disable-line import/no-extraneous-dependencies
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const push = require('./helper.js')
module.exports.update = async (event, context, callback) => {
const data = JSON.parse(event.body);
// validation
if (typeof data.userid !== 'string' || typeof data.restaurantid !== 'string' || typeof data.orderTime !== 'string' || typeof data.status !== 'string'
|| typeof data.confirmedtime !== 'string' || typeof data.expecteddeliverytime !== 'string' || typeof data.readytime !== 'string' || typeof data.contents !== 'string') {
console.error('Validation Failed');
callback(null, {
statusCode: 400,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t update the order',
});
return;
}
const params = {
TableName: process.env.ORDER_TABLE,
Key: {
id: event.pathParameters.id,
},
ExpressionAttributeNames: {
'#userid': 'userid',
'#restaurantid': 'restaurantid',
'#orderTime': 'orderTime',
'#status': 'status',
'#confirmedtime': 'confirmedtime',
'#expecteddeliverytime': 'expecteddeliverytime',
'#readytime': 'readytime',
'#contents': 'contents',
},
ExpressionAttributeValues: {
':userid': data.userid,
':restaurantid': data.restaurantid,
':orderTime': data.orderTime,
':status': data.status,
':confirmedtime': data.confirmedtime,
':expecteddeliverytime': data.expecteddeliverytime,
':readytime': data.readytime,
':contents': data.contents
},
UpdateExpression: 'SET #userid = :userid, #restaurantid = :restaurantid, #orderTime = :orderTime, #status = :status, #confirmedtime = :confirmedtime, #expecteddeliverytime = :expecteddeliverytime, #readytime = :readytime, #contents = :contents',
ReturnValues: 'ALL_NEW',
};
// update the address in the database
dynamoDb.update(params, (error, result) => {
// handle potential errors
if (error) {
console.error(error);
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t update the order.'
});
return;
}
// send push notification of new order status
var device_id = await push.GetDeviceIdFromHash(data.userid);
var push_data = push.generatePushNotification("Order status update!", data.status);
var res = push.sendPush(device_id, push_data);
console.log(device_id);
console.log(push_data);
// create a response
const response = {
statusCode: 200,
body: JSON.stringify(result.Attributes),
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
}
};
callback(null, response);
});
};
GetDeviceIdFromHashfunction, which is not returning aPromise. This is a good example of why to prefer TS and why to have linters. A second problem is that you are using the "callback" wrong, it is a function, if you return from it, it'll return from the callback, not your encapsulating scope. The upvoted answer is correct, unless you want to pass another callback function intoGetDeviceIdFromHash.