0

I am new to Node.js and Javascript and am developing an Alexa application using Lambda function and DynamoDB.
I have a table in DynamoDB named: Chat with PrimaryKey: 'Said' and a column 'say'. Whenever the Alexa skills is launched I just want to fetch a record based on what is said by the user and return. So its basically a single Query on the primary key which works fine.

However, I dont get any response from the lambda function in speech output variable as the API doesn't wait for the response builder to complete the async call to DynamoDB and returns a null response.
Is there any way to enforce the async call to be resolved before sending the response?

const WelcomeMessage = {
 canHandle(handlerInput) {
     const request = handlerInput.requestEnvelope.request;
     return request.type === 'LaunchRequest' ||
         (request.type === 'IntentRequest');
 },
 handle(handlerInput) {
     var ans;
     var AWS = require('aws-sdk');

     // Set the region 
     AWS.config.update({
         region: 'us-east-1'
     });

     // Create the DynamoDB service object
     var dynamodb = new AWS.DynamoDB();

     var params = {
         TableName: 'chat',
         Key: {
             'said': {
                 S: 'Hi Sir' + ''
             }
         },
         ProjectionExpression: 'say'
     };

     dynamodb.getItem(params, function(err, data) {
         if (err) {
             console.log(err, err.stack);
         } else {
             if (data) {
                 return handlerInput.responseBuilder
                     .speak(data.Item.say.S + '')
                     .getResponse();
             } else {
                 ans = 'You dint train me for that!';
                 return handlerInput.responseBuilder
                     .speak(ans)
                     .getResponse();
             }
         }
     });

 }
 };

Wrong Output:

enter image description here

Karan Sharma
  • 475
  • 1
  • 5
  • 16
  • Can you `console.log(data)`? Technically this is correct, `aws-sdk` still doesn't seem to support promises out of the box, but you do have the callback. So my guess is that it actually does wait for the response, but the response might be simply wrongly formatted. – ffritz Aug 24 '18 at 13:41

1 Answers1

0

I found a workaround. I return a promise and resolve it before I return it ensuring the callback to be completed before a response is sent.

const WelcomeMessage = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'LaunchRequest'
      || (request.type === 'IntentRequest');
  },
  handle(handlerInput) {
   
    return new Promise((resolve) => {

    var ans;
    var AWS = require('aws-sdk');
    // Set the region 
    AWS.config.update({region: 'us-east-1'});

    // Create the DynamoDB service object
    //ddb = new AWS.DynamoDB({apiVersion: '2012-10-08'});
    var dynamodb = new AWS.DynamoDB();
   
    var params = {
      TableName : 'chat',
      Key: {
        'said':{S: handlerInput.requestEnvelope.request.intent.slots.input.value+''}
      }
    };

    dynamodb.getItem(params, function(err, data) {
      
      if (err){ 
        console.log(err, err.stack);

      }
      else{ 
        if(data.Item){
          return resolve(handlerInput.responseBuilder
                .speak(data.Item.say.S+'')
                .withShouldEndSession(false)
                .getResponse());
        }  
        else{
          ans='You dint train me for that!';
          return resolve(handlerInput.responseBuilder
            .speak(ans)
            .withShouldEndSession(false)
            .getResponse());
        }
      }      
    });
   });
  }
};
Karan Sharma
  • 475
  • 1
  • 5
  • 16