问题
I keep getting an issue with the following code with Amazon Lambda and the alexa skills kit. I have spent countless hours on this and cannot get it to work. I keep getting this message returned and can't figure out why the http get is failing. "Please try again later". It isn't even printing the console messages.
var Alexa = require('alexa-sdk');
var http = require('http');
var APP_ID = "omitted";
var SKILL_NAME = 'omitted';
var options = {
host: 'api.forismatic.com',
path: '/api/1.0/?method=getQuote&lang=en&format=text',
method: 'GET'
};
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('Inspiration');
},
'IntentRequest': function() {
this.emit('Inspiration');
},
'InspirationIntent': function () {
this.emit('Inspiration');
},
'Inspiration': function () {
var speechOutput = '';
var text = '';
http.get(options, function(res) {
console.error("Got response: " + res.statusCode);
res.on("data", function(chunk) {
console.error("BODY: " + chunk);
text = chunk;
});
}).on('error', function(e) {
text = 'error' + e.message;
console.error("Got error: " + e.message);
});
if(text == ''){
speechOutput = "Please try again later";
}
else{speechOutput = text;}
this.emit(':tellWithCard', speechOutput, SKILL_NAME, text);
},
'AMAZON.HelpIntent': function () {
var speechOutput = "You can ask Inspirational Quote for some advice.";
var reprompt = "What would you like me to do?";
this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', 'Goodbye!');
},
'AMAZON.StopIntent': function () {
this.emit(':tell', 'Goodbye!');
},
'Unhandled': function() {
this.emit('AMAZON.HelpIntent');
}
};
回答1:
Because java script is asynchronous, this code :
if(text == ''){
speechOutput = "Please try again later";
}
else{speechOutput = text;}
this.emit(':tellWithCard', speechOutput, SKILL_NAME, text);
is running before the call out to the API gets a response.
Unfortunately, you can't just move the above code to inside the http.get block, as the 'this' in 'this.emit' will no longer work and you'll get an undefined response being sent back to the Alexa Skill.
I think the neatest solution would be to pull the http call out into a separate function. When calling that function, you will have to use a callback to avoid the same issue of the lambda not waiting for a response from the http call before moving to the next code line. So pass a function with the function call and send your response from there. NB - for this to work you have to assign a variable to the value of 'this' outside the function call and use that variable instead of 'this', inside the function call.
Example below:
var Alexa = require('alexa-sdk');
var http = require('http');
var APP_ID = "omitted";
var SKILL_NAME = 'omitted';
var options = {
host: 'api.forismatic.com',
path: '/api/1.0/?method=getQuote&lang=en&format=text',
method: 'GET'
};
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('Inspiration');
},
'IntentRequest': function() {
this.emit('Inspiration');
},
'InspirationIntent': function () {
this.emit('Inspiration');
},
'Inspiration': function () {
var speechOutput = '';
var text = '';
var self = this;
getQuote(options, function (quote){
if(quote == ''){
speechOutput = "Please try again later";
}
else{speechOutput = quote;}
self.emit(':tellWithCard', speechOutput, SKILL_NAME, text);
}
)},
'AMAZON.HelpIntent': function () {
var speechOutput = "You can ask Inspirational Quote for some advice.";
var reprompt = "What would you like me to do?";
res(this.emit(':ask', speechOutput, reprompt));
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', 'Goodbye!');
},
'AMAZON.StopIntent': function () {
this.emit(':tell', 'Goodbye!');
},
'Unhandled': function() {
this.emit('AMAZON.HelpIntent');
}
};
function getQuote(options, callback){
http.get(options, function(res) {
console.error("Got response: " + res.statusCode);
res.on("data", function(chunk) {
console.error("BODY: " + chunk);
text = '' + chunk;
return callback(text);
});
}).on('error', function(e) {
text = 'error' + e.message;
console.error("Got error: " + e.message);
});
}
来源:https://stackoverflow.com/questions/42354742/amazon-aws-lambda-alexa-http-get-issue