Amazon Alexa Skill Lambda Node JS - HETP GET не работает
Мне интересно, может ли кто-нибудь помочь, потому что я бью себя головой об стену с этим. Я искал ответы в течение нескольких дней и пробовал разные вещи, и ниже - самое близкое, что у меня есть.
По сути, я создаю навык Alexa для личного использования в своем доме, чтобы дать призовые очки моему сыну, и он обновляется на нашей информационной панели. Я могу POST очков нормально и приборной панели обновляется (обновляет базу данных Firebase), но я не могу получить очки, когда я спрашиваю Алекса, сколько у него есть. Мой код ниже.
const GetPointsHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'HowManyPointsDoesNameHaveIntent';
},
handle(handlerInput) {
var options = {
"method": "GET",
"hostname": "blah-blah-blah.firebaseio.com",
"port": null,
"path": "/users/Connor/points.json",
"headers": {
"cache-control": "no-cache"
}
};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
//console.log(body.toString());
total = body.toString();
});
});
req.end();
speechOutput = "Connor has " + total + " points";
return handlerInput.responseBuilder
.speak(speechOutput)
.getResponse();
},
};
В тот момент, когда я спрашиваю Алексу, "Коннор имеет неопределенные баллы", но если я сразу же спрашиваю, все работает нормально.
Конечная точка json буквально показывает значение, когда я загружаю его в браузере, поэтому не нужно копаться в ответе, который я не думаю.
Я знаю, что модуль запроса должен быть проще, но если я установлю его с помощью командной строки кода VS и загрузу функцию, поскольку файл становится настолько большим со всеми зависимостями модуля, я больше не могу редактировать функцию онлайн, как она есть. за пределы размера, поэтому, если возможно, хотите избежать этого.
Я знаю, что эту функцию лучше разместить в качестве помощника, что я сделаю, как только получу эту работу. Мне не нужно, чтобы это было особенно красиво, просто нужно, чтобы это работало.
2 ответа
Это из-за асинхронного поведения nodejs. Узел не будет ждать твоего http
просьба завершить. Итак speechOutput = "Connor has " + total + " points";
выполняется еще до того, как значение total
взято. Следовательно, undefined
,
Чтобы сделать эту работу, вы должны использовать Promises
, Написать отдельную функцию для огня http
Запросы. Проверьте это PetMatchSkill и посмотрите, как это делается. Вы можете использовать это как общий метод для любых запросов.
Пример:
function httpGet(options) {
return new Promise(((resolve, reject) => {
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
if (response.statusCode < 200 || response.statusCode >= 300) {
return reject(new Error(`${response.statusCode}: ${response.req.getHeader('host')} ${response.req.path}`));
}
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
Теперь в вашем намерении использовать обработчик async
-await
,
async handle(handlerInput) {
var options = {
"method": "GET",
"hostname": "blah-blah-blah.firebaseio.com",
"port": null,
"path": "/users/Connor/points.json",
"headers": {
"cache-control": "no-cache"
}
};
const response = await httpGet(options);
var total = 0;
if (response.length > 0) {
// do your stuff
//total = response
}
speechOutput = "Connor has " + total + " points";
return handlerInput.responseBuilder
.speak(speechOutput)
.getResponse();
}
Node.js по умолчанию является асинхронным, что означает, что ваш построитель ответов вызывается до завершения запроса GET.
Решение: используйте async-await, как-то так
async handle(handlerInput) {
var options = {
"method": "GET",
"hostname": "blah-blah-blah.firebaseio.com",
"port": null,
"path": "/users/Connor/points.json",
"headers": {
"cache-control": "no-cache"
}
};
var req = await https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
//console.log(body.toString());
total = body.toString();
});
});
req.end();
speechOutput = "Connor has " + total + " points";
return handlerInput.responseBuilder
.speak(speechOutput)
.getResponse();
},
Дайте мне знать, если это не сработает. Также, чтобы развить навыки Алексы для личного использования, проверьте чертежи Алексы.