Javascript “如何排除故障”;“南”;当对函数的调用和分配给let是唯一可见的问题时出错
我正在本地测试Alexa技能,结果出现了一个错误,上面写着NaN。通过Javascript “如何排除故障”;“南”;当对函数的调用和分配给let是唯一可见的问题时出错,javascript,node.js,asynchronous,nan,alexa,Javascript,Node.js,Asynchronous,Nan,Alexa,我正在本地测试Alexa技能,结果出现了一个错误,上面写着NaN。通过console.log()语句,我发现行let recipe=getRecipe()是问题所在。它似乎不在getRecipe()函数本身中,因为该函数中try块最开头的console.log()语句没有运行,但catch开头的语句运行。提前感谢您的建议 处理程序: 句柄(handlerInput){ const attributes=handlerInput.AttributeManager.getSessionAttribu
console.log()
语句,我发现行let recipe=getRecipe()
是问题所在。它似乎不在getRecipe()
函数本身中,因为该函数中try块最开头的console.log()
语句没有运行,但catch开头的语句运行。提前感谢您的建议
处理程序:
句柄(handlerInput){
const attributes=handlerInput.AttributeManager.getSessionAttributes();
const request=handlerInput.requestEnvelope.request;
开关(attributes.previousIntent){
案例“Foodinent”:
if(request.intent.slots.answer.resolutions.resolutionsPerAuthority[0].values[0].value.name=='yes'){
让randomFood=Helpers.suggestFood(handlerInput);
让queryFood=randomFood.replace(/\s+/g,'-').toLowerCase();事件
attributes.currentSuggestedFood=queryFood;
const speechText='太好了!以后我可以帮你查配料了。'
console.log('before call getRecipe()')
let recipe=getRecipe(handlerInput)
console.log('After call getRecipe()')
返回handlerInput.responseBuilder
.speak(speechText+“”+配方)
.reprompt(演讲稿)
.WithShoulEndSession(真)
.withSimpleCard('Chear Up-YesNo',speechText)
.getResponse();
}否则{
让randomFood=Helpers.suggestFood(handlerInput);
让speechText=ResponseToUsersNo[Math.floor(Math.random()*ResponseToUsersNo.length)]+
FoodPrefixes[Math.floor(Math.random()*FoodPrefixes.length)]+
randomFood+FoodSuffix[Math.floor(Math.random()*FoodSuffix.length)];
let repromptText='上一个建议对你有用吗?'
handlerInput.attributesManager.setSessionAttributes(属性);
如果(attributes.FoodsAlreadySuggested.length>=10){
speechText='我觉得你其实什么都不想要。所以我现在就走,待会儿再跟你谈。'
返回handlerInput.responseBuilder
.发言(演讲稿)
.WithShoulEndSession(真)
.withSimpleCard('Chear Up-YesNo',speechText)
.getResponse();
}
返回handlerInput.responseBuilder
.发言(演讲稿)
.reprompt(repromptText)
.withSimpleCard('Chear Up-YesNo',speechText)
.getResponse();
}
案例“HobbyIntent”:
if(request.intent.slots
const attributes=handlerInput.attributesManager.getSessionAttributes()抛出错误NaN,原因仍然未知
catch()处理程序捕获并记录此错误。
但是由于函数是异步的,并且您没有在catch子句中解析承诺,因此您得到的是该承诺的字符串化版本,而不是实际的成分列表
编辑:
您是否考虑过使用util.promisify()以便不必混合回调和承诺
const { promisify } = require( 'util' );
const request = require( 'request' );
const get = promisify( request.get );
function getRecipe(handlerInput) {
const attributes = handlerInput.attributesManager.getSessionAttributes();
const url = `https://api.edamam.com/search?q=${attributes.currentSuggestedFood}&app_id=${FOOD_APP_ID}&app_key=${FOOD_APP_KEY}`; //&from=0&to=3&calories=591-722&health=alcohol-free this was on the end of the uri
return get( url, ( response, body ) => {
const payload = JSON.parse(body)
return payload.hits[0].recipe.ingredientLines;
}).catch( error ) {
console.error( `failed GET request for: ${ url }` );
console.error( error );
});
};
同样可以用async/await风格编写,但我的语言不够流利,无法在自己无法测试代码的情况下100%正确。最后我找到了答案。非常感谢@Shilly为我指明了正确的方向。我对async和await的理解是错误的。这些来源很有帮助: 这是我的更新代码: 异步处理程序依赖于我创建的一个函数,该函数在@Shilly的帮助下使用Promissions。这可能不是最简洁的方法,但它可以工作 处理程序:
async handle(handlerInput){
const attributes = handlerInput.attributesManager.getSessionAttributes();
const request = handlerInput.requestEnvelope.request;
switch (attributes.previousIntent){
case "FoodIntent":
if(request.intent.slots.answer.resolutions.resolutionsPerAuthority[0].values[0].value.name === 'yes'){
let randomFood = Helpers.suggestFood(handlerInput);
let queryFood = randomFood.replace(/\s+/g, '-').toLowerCase();
attributes.currentSuggestedFood = queryFood;
const speechText = 'Great! Here are the ingredients!'
let recipe = await getRecipe(handlerInput)
let recipeIngredients = recipe.hits[0].recipe.ingredientLines;
return handlerInput.responseBuilder
.speak(speechText+ 'The ingredients are '+ recipeIngredients)
.reprompt(speechText)
.withShouldEndSession(true)
.withSimpleCard('Cheer Up - YesIntentFood', recipeIngredients)
.getResponse();
功能:
async function getRecipe(handlerInput) {
const attributes = handlerInput.attributesManager.getSessionAttributes();
const url = `https://api.edamam.com/search?q=${attributes.currentSuggestedFood}&app_id=${FOOD_APP_ID}&app_key=${FOOD_APP_KEY}`;
console.log(url)
return new Promise (function(resolve, reject) {
request.get(url, (error, response, body) => {
if (error) {
reject(error);
} else {
resolve(JSON.parse(body))
}
});
})
};
输出:
https://api.edamam.com/search?q=pernil&app_id=b4dbea92&app_key=8d916c99b930b77c8cbb4615f0800df7
{ version: '1.0',
response:
{ outputSpeech:
{ type: 'SSML',
ssml: '<speak>Great! In the future I will be able to look up the ingredients for you.The ingredients are 2 1/2 pounds pork shoulder, boston butt, pernil,2 garlic cloves,1 small onion,1 bunch cilantro,1 jalapeño,1 cup orange juice,1 cup pineapple juice,1 lemon,Handfuls salt,Pepper to taste,Ground cumin</speak>' },
reprompt: { outputSpeech: [Object] },
shouldEndSession: true,
card:
{ type: 'Simple',
title: 'Cheer Up - YesIntentFood',
content: [Array] } },
userAgent: 'ask-node/2.3.0 Node/v8.12.0',
sessionAttributes:
{ foodType: 'PuertoRican',
FoodsAlreadySuggested: [ 'Platanos Maduros', 'Pernil' ],
previousIntent: 'FoodIntent',
state: '_YES_NO',
currentSuggestedFood: 'pernil' } }
https://api.edamam.com/search?q=pernil&app_id=b4dbea92&app_key=8d916c99b930b77c8cbb4615f0800df7
{版本:“1.0”,
答复:
{输出语音:
{type:'SSML',
ssml:“太好了!以后我会帮你查配料的。配料有2 1/2磅猪肩、波士顿屁股、培尼、2个蒜瓣、1个小洋葱、1束香菜、1个墨西哥辣椒、1杯橙汁、1杯菠萝汁、1个柠檬、一把盐、调味胡椒、孜然粉”},
reprompt:{outputSpeech:[对象]},
shouldEndSession:true,
卡片:
{type:'简单',
标题:“振作起来-是的,食物”,
内容:[Array]},
userAgent:'ask node/2.3.0 node/v8.12.0',
会期贡献:
{foodType:'葛根素',
食物建议:[“普拉塔诺斯马杜罗斯”、“佩尼”],
先前的意图:“食物性”,
声明:‘‘是’或‘否’,
currentSuggestedFood:'pernil'}
在您的输出中,url之前的从不记录。因此我们需要查看handleInput.AttributeManager.getSessionAttributes();
method谢谢你的回答。@Shilly我更新了代码。在url打印之前,我已经更新了代码。我确实从属性调用中得到了一个对象承诺。仍然有点困惑,但你让我走上了正确的轨道。谢谢。奇怪的是,@Shilly,当我打印url时,它将我所需的值作为查询字符串,从会话a中收集ttributes。我将查看更新的代码和更新的错误日志。由于回调、Promises和async/await的混合,promise仍然存在无法正确解决的问题。由于您使用node.js,您是否尝试过promisify()
?这将允许您返回或等待请求。get()调用。我将在edit.Updated中添加代码。显示的代码确实希望使用承诺链来获取配方,因此let recipe=getRecipe(handlerInput)。然后(…);
,但如果需要,可以将其编写为异步/等待。