I want to call an api from a Lambda function. My handler is triggered by an intent which includes two required slots. Therefore I don't know in advance whether I will be returning a Dialog.Delegate
directive or my response from the api request. How do I promise these return values by the time the intent handler is called?
This is my handler:
const FlightDelayIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'MyIntent';
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
if (request.dialogState != "COMPLETED"){
return handlerInput.responseBuilder
.addDelegateDirective(request.intent)
.getResponse();
} else {
// Make asynchronous api call, wait for the response and return.
var query = 'someTestStringFromASlot';
httpGet(query, (result) => {
return handlerInput.responseBuilder
.speak('I found something' + result)
.reprompt('test')
.withSimpleCard('Hello World', 'test')
.getResponse();
});
}
},
};
This is my helper function which makes the request:
const https = require('https');
function httpGet(query, callback) {
var options = {
host: 'myHost',
path: 'someTestPath/' + query,
method: 'GET',
headers: {
'theId': 'myId'
}
};
var req = https.request(options, res => {
res.setEncoding('utf8');
var responseString = "";
//accept incoming data asynchronously
res.on('data', chunk => {
responseString = responseString + chunk;
});
//return the data when streaming is complete
res.on('end', () => {
console.log('==> Answering: ');
callback(responseString);
});
});
req.end();
}
So I suspect I will have to use promises and put an "async" in front of my handle function? I am very new to all of this so I don't know the implications of this, especially considering the fact that I have two different return values, one directly and the other one delayed. How would I solve this?
Thank you in advance.
As you suspected, your handler code is finishing before the asynchronous call to http.request, hence the Alexa SDK receives no return value from the
handle
function and will return an invalid response to Alexa.I slightly modified your code to run it locally on a laptop to illustrate the issue :
To run this code, do not forget
npm install http
, thennode test.js
. It producesSo, the key is to wait for
http get
to return before to return a response to Alexa. For that, I propose to modify yourhttpGet
function to return a promise instead using callbacks.Modified code is like this (I kept your original code as comment)
Running this code produces :