3

In one of the intent handler for my Alexa skill I have to return response once my promise is resolved.

Code looks like this :

var rcvPromise = receiveMsgQ();    
rcvPromise.then(function(speechText) { 
   console.log('rcv Promise resolved with ',speechText);    
   return handlerInput.responseBuilder
       .speak(speechText) 
       .withSimpleCard('skill_name', speechText) 
       .withShouldEndSession(false)
       .getResponse();        
   });

Skill returns with ERROR message with no additional details about error.

Is there any way to fix this problem?

PS: I need to use promise as receiveMsgQ() is asynchronous function call.

johndoe
  • 4,387
  • 2
  • 25
  • 40

1 Answers1

5

The error you're seeing is because NodeJS and the Alexa SDK are asynchronous. As you can read from the Alexa SDK code, it invokes your request handlers and expects a Promise back. In your example, as your code does not return anything explicitly after calling rcvPromise.then, an empty response is sent back, and the SDK sends an empty response to Alexa, causing the error. When your then() function will be executed, the Alexa response has already been sent and your handlerInput.responseBuilder result is ignored.

To solve this problem, you have two solutions:

a/ you can insert a return statement before rcvPromise.then, such as

return rcvPromise.then(function(speechText) {
   console.log('rcv Promise resolved with ',speechText);
     return handlerInput.responseBuilder
       .speak(speechText) 
       .withSimpleCard('skill_name', speechText) 
       .withShouldEndSession(false)
       .getResponse();
 });   

This way, your handler will return a Promise to the SDK and the SDK will use the result of the promise to build the response to send to Alexa.

b/ If you are using NodeJS 8, you can use the new await/async syntax. Under the hood, it is the same as the above solution, but it will make the code easier to read.

var speechText = await receiveMsgQ();
console.log('rcv Promise resolved with ',speechText);
return handlerInput.responseBuilder
       .speak(speechText) 
       .withSimpleCard('skill_name', speechText) 
       .withShouldEndSession(false)
       .getResponse();

Note that your entire handler function must be marked as async for this to work. Read more about async and await at https://blog.risingstack.com/mastering-async-await-in-nodejs/

Sébastien Stormacq
  • 14,301
  • 5
  • 41
  • 64