Я создаю навык Alexa, связанный с лямбда-функцией AWS.Для некоторых целей мне нужно сделать http-запрос, и это может не получиться из-за задержки соединения, которую я не могу предсказать.Проблема в том, что лямбда прерывает мое выполнение, если я использую более 128 МБ или выполнение занимает более 7000 мс.Так как я не хочу увеличивать свой лимит времени, я искал способ предотвратить лямбду, отправляющую сообщение об ошибке моему навыку Alexa, который сообщит мне, что возникла проблема, но отправит себе сообщение о том, что соединение может быть медленным, и Alexa не можетне могу найти то, что спросил пользователь.
Я попытался получить доступ к отчету консоли, чтобы проверить наличие ошибки тайм-аута, но я новичок в nodejs и не могу предотвратить лямбда-отправку этой ошибки в Alexa.
Это мой лямбда-код:
var https = require('https');
const fs = require('fs');
let speechOutput;
let reprompt;
let welcomeOutput = "Salve Guardiano, per ora puoi chiedermi cosa porta Xur questa settimana, quali cala la notte ci sono, dove si trova focolai o anche in che stato si trova la città sognante.";
let welcomeReprompt = "Come posso aiutarti?";
"use strict";
const Alexa = require('alexa-sdk');
const APP_ID = undefined; // TODO replace with your app ID (OPTIONAL).
speechOutput = '';
const handlers = {
'LaunchRequest': function () {
this.emit(':ask', welcomeOutput, welcomeReprompt);
},
'AMAZON.HelpIntent': function () {
speechOutput = 'Per ora puoi chiedermi cosa porta Xur questa settimana, quali cala la notte ci sono, dove si trova focolai o anche in che stato si trova la città sognante.';
this.emit(':ask', speechOutput);
},
'AMAZON.CancelIntent': function () {
speechOutput = 'Ok, cancello.';
this.emit(':tell', speechOutput);
},
'AMAZON.StopIntent': function () {
speechOutput = 'Arrivederci, non camperare troppo.';
this.emit(':tell', speechOutput);
},
'SessionEndedRequest': function () {
speechOutput = '';
//this.emit(':saveState', true);//uncomment to save attributes to db on session end
this.emit(':tell', speechOutput);
},
'AMAZON.NavigateHomeIntent': function () {
speechOutput = '';
//any intent slot variables are listed here for convenience
//Your custom intent handling goes here
speechOutput = "Chiedimi aiuto.";
this.emit(":ask", speechOutput);
},
'informazioni_settimanali': async function () {
//prendo il codice corrispondente allo slot comunicato
let activityID = this.event.request.intent.slots.activity.resolutions.resolutionsPerAuthority[0].values[0].value.id;
//prendo il token di accesso
let token = this.event.context.System.user.accessToken;
speechOutput = '';
speechOutput = await richiesta_activities(activityID);
speechOutput = speechOutput + "Posso fare altro per la tua luce?"
this.emit(":ask", speechOutput );
},
'xur_location': async function () {
speechOutput='Non ho ancora sviluppato questa funzionalità. Posso aiutarti in altro modo?';
this.emit(":ask", speechOutput, speechOutput);
},
'what_sells_xur': async function () {
//prendo il token di accesso
let token = this.event.context.System.user.accessToken;
if(token==null){
speechOutput = 'Per richiedere questo tipo di informazioni devi collegare il tuo account Bungie alla skill Spettro dall\'app Alexa.';
this.emit(":tellWithLinkAccountCard",speechOutput);
}else{
speechOutput='';
speechOutput = await xur_inventory(token);
speechOutput = speechOutput + " Posso fare altro per la tua luce?"
this.emit(":ask", speechOutput );
}
},
'Unhandled': function () {
speechOutput = "Perdonami, non ho capito.";
this.emit(':ask', speechOutput, speechOutput);
}
};
exports.handler = (event, context,callback) => {
const alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
// To enable string internationalization (i18n) features, set a resources object.
//alexa.resources = languageStrings;
alexa.registerHandlers(handlers);
//alexa.dynamoDBTableName = 'DYNAMODB_TABLE_NAME'; //uncomment this line to save attributes to DB
alexa.execute();
};
// END of Intent Handlers {} ========================================================================================
async function xur_inventory(token){
let Hash='2190858386'; //xur's hash
let endpoint = '/Platform/Destiny2/2/Profile/4611686018456602435/Character/2305843009289717384/Vendors/?components=vendorsales';
const response = await httpTokenGet(endpoint,token);
let ans='';
//console.log(response);
if(response.Response.sales.data[Hash]!=null){
let items = new Array();
var i=0;
let temp;
temp = response.Response.sales.data[Hash].saleItems;
for(var key in temp){
//console.log(key);
//console.log(temp[key].itemHash);
items[i]=temp[key].itemHash;
i++;
}
//LETTURA AGGIORNATA DAL WEB
let jsonendpoint = '/it/reducedCollectableInventoryItems.json';
const DestinyItems = await httpJsonGet(jsonendpoint);
//console.log(DestinyItems);
let itemsPlain = new Array();
let itemsType = new Array();
for(let i=0;i<items.length;i++){
if(DestinyItems[items[i]]!=null){
itemsPlain[i]=DestinyItems[items[i]].displayProperties.name;
itemsType[i]=DestinyItems[items[i]].itemTypeDisplayName;
//console.log(itemsPlain[i]);
//console.log(itemsType[i]);
}
}
ans = "Ecco cosa vende Xur: ";
for (var i=0;i<itemsPlain.length;i++){
ans = ans + itemsPlain[i] + " ("+ itemsType[i]+"). ";
}
return ans;
}else {
return "Mi spiace non riesco a trovare Xur. ";
}
}
async function richiesta_activities(activityID,token){
//this function returns the activity's infos selected by the user
let endpoint = '';
if(activityID==0){
//cala la notte
let Hash='2171429505';
endpoint = '/Platform/Destiny2/Milestones/';
const response = await httpGet(endpoint);
let nightfalls = new Array();
if(response.Response[Hash]!=null){
for(let i=0;i<3;i++){
nightfalls[i]=response.Response[Hash].activities[i].activityHash;
}
//LETTURA AGGIORNATA DAL WEB
let jsonendpoint = '/en/reducedActivities.json';
const Destinyactivities = await httpJsonGet(jsonendpoint);
let nightfallsPlain = new Array();
for(let i=0;i<3;i++){
nightfallsPlain[i]=Destinyactivities[nightfalls[i]].displayProperties.name;
console.log(nightfallsPlain[i]);
}
let ans = "Ecco i cala la notte che ho trovato: ";
for (var i=0;i<3;i++){
let end=nightfallsPlain[i].lengt;
nightfallsPlain[i]=nightfallsPlain[i].substring(10,end);
ans = ans + nightfallsPlain[i] + ", ";
}
return ans;
}
else{
return "Purtroppo non riesco ad aiutarti.";
}
}
else if(activityID==1){
//focolai
let Hash = '463010297';
endpoint = '/Platform/Destiny2/Milestones/';
const response = await httpGet(endpoint);
if(response.Response[Hash]!=null){
var flashpoint = response.Response[Hash].availableQuests[0].questItemHash;
console.log(flashpoint);
var text = '';
//LETTURA DAL WEB
let jsonendpoint = 'https://destiny.plumbing/en/raw/DestinyInventoryItemDefinition.json';
const DestinyFlashpoint = await httpJsonGet(jsonendpoint);
if(DestinyFlashpoint[flashpoint]!=null){
console.log(DestinyFlashpoint[flashpoint]);
let flashpointPlain = DestinyFlashpoint[flashpoint].displayProperties.name;
let location=flashpointPlain.substring(10,flashpointPlain.length);
return "Questa settimana, il focolaio si trova su "+location+".";
}else{
return "Purtroppo non riesco ad aiutarti.";
}
}else{
return "Purtroppo non riesco ad aiutarti.";
}
}else{
return "Devo ancora sviluppare le altre attività.";
}
}
function httpTokenGet(endpoint,token) {
return new Promise(((resolve, reject) => {
var options = {
host: 'www.bungie.net',
path: endpoint,
method: 'GET',
headers: {'X-API-KEY': 'xxxxxxxxxxxxxxxxxxxxxx',
'Authorization': 'Bearer '+ token},
};
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
function httpGet(endpoint) {
return new Promise(((resolve, reject) => {
var options = {
host: 'www.bungie.net',
path: endpoint,
method: 'GET',
headers: {'X-API-KEY': 'xxxxxxxxxxxxxxxxxxxxxx'},
};
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
function httpJsonGet(endpoint) {
return new Promise(((resolve, reject) => {
var options = {
host: 'destiny.plumbing',
path: endpoint,
method: 'GET',
};
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
Проблема может возникнуть здесь в функции async function richiesta_activities(activityID,token)
//LETTURA DAL WEB
let jsonendpoint = 'https://destiny.plumbing/en/raw/DestinyInventoryItemDefinition.json';
const DestinyFlashpoint = await httpJsonGet(jsonendpoint);
, когда я вызываю await httpJsonGet(jsonendpoint);
На самом делево время тестирования лямбда-консоли записывает следующее:
Response:
{
"errorMessage": "2019-03-27T17:21:48.437Z 855210e7-4c89-474b-af57-0bdd3e9d89d5 Task timed out after 7.01 seconds"
}
Request ID:
"855210e7-4c89-474b-af57-0bdd3e9d89d5"
Function Logs:
START RequestId: 855210e7-4c89-474b-af57-0bdd3e9d89d5 Version: $LATEST
2019-03-27T17:21:41.520Z 855210e7-4c89-474b-af57-0bdd3e9d89d5 Warning: Application ID is not set
END RequestId: 855210e7-4c89-474b-af57-0bdd3e9d89d5
REPORT RequestId: 855210e7-4c89-474b-af57-0bdd3e9d89d5 Duration: 7007.93 ms Billed Duration: 7000 ms Memory Size: 128 MB Max Memory Used: 128 MB
2019-03-27T17:21:48.437Z 855210e7-4c89-474b-af57-0bdd3e9d89d5 Task timed out after 7.01 seconds
Но Алекса говорит, что была проблема с навыком.Как я могу предотвратить эту ситуацию и самостоятельно обработать ее, чтобы она не возвращала ошибку?
РЕДАКТИРОВАТЬ: Благодаря вам работает обработчик тайм-аута @Deiv.
Я все еще хочу найти способ доступа к лямбда-отчетупотому что я заметил, что у меня может быть недостаточно памяти, даже если выполнение длится менее 7000 мс, и было бы неплохо справиться с этой ситуацией.