Closed NovaGL closed 7 years ago
If you're trying to handle an intent asynchronously, you'll need the code that fires off your network request to use promises rather than a callback function, and have the intent function return that promise. Without that, the library won't know to wait for your asynchronous call to return before sending a response to Amazon.
Without knowing where your httpsGet
function is coming from or if it's something you can modify, a hypothetical Promise-based version might maybe look something like this:
alexaApp.intent('Test', {},
function(req, res) {
return httpsGet(myRequest).then((myResult) => {
console.log("sent : " + myRequest);
console.log("received : " + myResult);
res.say('The population of ' + myRequest + ' is ' + myResult);
});
});
});
(You'll notice I also removed the this
from res.say
. I also removed the this.emit
call — that's something that's part of the official Alexa JS SDK, but doesn't exist / isn't necessary in the alexa-app
library)
Hope that's helpful!
Thanks for that @lazerwalker. I think you have too many closing brackets.
EDIT: So I think I have done it now. Can you tell me if I need to correct anything in my code I'm a real newbie with Node.JS but I like to give it a go.
alexaApp.intent('test', {},
function(req, res) {
return httpsRequest(myRequest).then((myResult) => {
console.log("sent : " + myRequest);
console.log("received : " + myResult);
res.say('The population of ' + myRequest + ' is ' + myResult);
});
});
function httpsRequest(myData, postData) {
var params = {
host: 'cp6gckjt97.execute-api.us-east-1.amazonaws.com',
port: 443,
path: '/prod/stateresource?usstate=' + encodeURIComponent(myData),
method: 'GET',
// if x509 certs are required:
// key: fs.readFileSync('certs/my-key.pem'),
// cert: fs.readFileSync('certs/my-cert.pem')
};
return new Promise(function(resolve, reject) {
var req = https.request(params, function(res) {
// reject on bad status
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
// cumulate data
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
// resolve on end
res.on('end', function() {
try {
body = JSON.parse(body).population;
} catch(e) {
reject(e);
}
resolve(body);
});
});
// reject on request error
req.on('error', function(err) {
// This is not a "Second reject", just a different sort of failure
reject(err);
});
if (postData) {
req.write(postData);
}
// IMPORTANT
req.end();
});
}
Yeah, that seems pretty reasonable!
If that's giving you trouble, you might want to investigate pre-existing node libraries that provide a Promise-based API to make HTTP requests, such as https://github.com/request/request-promise (you'll find tons more at npmjs.com, I haven't used that one specifically).
You may also want to check out the async section of the readme for this project: https://github.com/alexa-js/alexa-app#asynchronous-handlers-example. The README in general is likely to be more useful to you than Amazon's alexa-cookbook examples, as alexa-app
operates fairly differently from the official Alexa JS SDK.
Thanks. Don't really understand your async examples but doesn't really matter.
I am trying to make my own Alexa Sonos skill which could be adapted to control any music system that provides metadata.
This particular function is used for getting the now playing info. I will also adapt it to get the favorites of a player, but that's the next step.
It will never be released as it's for private use but hopefully I can give the source out so people can do their own stuff if it ever gets to that level.
I need some help, Async gets me all confused sync I am a novice in Node-Red.
I just want Alexa to say something it receives from a HTTPS Call. I am using (https://github.com/alexa/alexa-cookbook/blob/master/external-calls/httpsGet/src/index.js) as an example but I don't know how to adapt it to use Alexa app. Any help would be great.
Not sure if this is right
The console log shows the correct info. But it goes wrong from there.