Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/466.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript “如何排除故障”;“南”;当对函数的调用和分配给let是唯一可见的问题时出错_Javascript_Node.js_Asynchronous_Nan_Alexa - Fatal编程技术网

Javascript “如何排除故障”;“南”;当对函数的调用和分配给let是唯一可见的问题时出错

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

我正在本地测试Alexa技能,结果出现了一个错误,上面写着NaN。通过
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)。然后(…);
,但如果需要,可以将其编写为异步/等待。