Alexa Skill Learning: TypeError: Cannot read property 'value' of undefined

Alexa Skill Learning: TypeError: Cannot read property 'value' of undefined

当我尝试测试我的基本技能(我正在尝试学习如何创建它们)时,我总是遇到错误。 这是日志中的错误:

2018-11-21T16:10:55.759Z 06a36441-eda8-11e8-a421-f996bf66c592 Unexpected exception 'TypeError: Cannot read property 'value' of undefined':

TypeError: Cannot read property 'value' of undefined at Object.getSuggestion (/var/task/index.js:31:54) at emitNone (events.js:86:13) at AlexaRequestEmitter.emit (events.js:185:7) at AlexaRequestEmitter.EmitEvent (/var/task/node_modules/alexa-sdk/lib/alexa.js:216:10) at AlexaRequestEmitter.ValidateRequest (/var/task/node_modules/alexa-sdk/lib/alexa.js:181:23) at AlexaRequestEmitter.HandleLambdaEvent (/var/task/node_modules/alexa-sdk/lib/alexa.js:126:25) at AlexaRequestEmitter.value (/var/task/node_modules/alexa-sdk/lib/alexa.js:100:31)

at exports.handler (/var/task/index.js:52:9)

我该如何解决这个问题?

这是我的代码:

var Alexa = require('alexa-sdk');


const APP_ID = 'amzn1.ask.skill.ab07421a-0a92-4c2b-b3bd-998e14286xxx';


const skillData = [
    {
        city: "Austin",
        suggestion: "Austin has some of the most outstanding people."
    },
    {
        city: "San Antonio",
        suggestion: "San Antonio has some of the most outstanding people."    
    },
    {
        city: "Dallas",
        suggestion: "The Dallas metroplex is one of the hottest places."
    }
];


var number = 0;
while(number<3){
var handlers = {
  'LaunchRequest': function () {


      this.emit(':ask', 'Tell me the name of the major city you are closest to'
   },
  'Unhandled': function () {
      this.emit(':ask', 'Try saying a city name like Austin, San Antonio, or Dallas'); 
  },
  'getSuggestion': function() {
      var city = this.event.request.intent.slots.City.value;


      this.emit(':ask', getSuggestion(skillData,'city', city.toUpperCase()).suggestion + '. Give me another city and I\'ll hook you up with the best peeps.');
  },
  'AMAZON.HelpIntent': function () {
      this.emit(':ask', "What can I help you with?", "How can I help?");
  },
  'AMAZON.CancelIntent': function () {
      this.emit(':tell', "Okay!");
  },
  'AMAZON.StopIntent': function () {
      this.emit(':tell', "Goodbye!");
  },
};
number = number+1;
}


exports.handler = function(event, context, callback){
  var alexa = Alexa.handler(event, context);
  alexa.appId = APP_ID;
  alexa.registerHandlers(handlers);
  alexa.execute();
};


function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {
    if (arr[i][propName] == cityName) {
      return arr[i];
    }
  }
}

更新

我已经按照下面的建议进行了一些更改,但是,在初始响应后我仍然收到错误消息。

"errorMessage": "Cannot read property 'city' of undefined"

请查看我的新代码并帮助我解决这个问题:

var Alexa = require('alexa-sdk');

const APP_ID = 'amzn1.ask.skill.ab07421a-0a92-4c2b-b3bd-998e14286xxx';

const skillData = [
    {
        city: 'Austin',
        suggestion: "Austin is blahblahblahblahlshflashdfasldfha blah."
    },
    {
        city: 'San Antonio',
        suggestion: "San Antonio has blahblahblahblahlshflashdfasldfha blah."    
    },
    {
        city: 'Dallas',
        suggestion: "The Dallas metroplex is one of the hottest blahblahblahbla blahblahblahblahblahblah."
    }
];

var number = 0;
while(number<3){
var handlers = {
  'LaunchRequest': function () {
      this.emit(':ask', 'Tell me the name of the major city you are closest to!', 'Which major city are you closest to?');
   },
  'Unhandled': function () {
      this.emit(':ask', "Try saying a city name like Austin, San Antonio, or Dallas"); 
  },
  'getSuggestion': function() {
      var city = this.event.request.intent.slots.city.value;

      this.emit(':ask', getSuggestion(skillData,'city', city.toUpperCase()).suggestion + '. Give me another city and I\'ll hook you up with the best peeps.');
  },
  'AMAZON.HelpIntent': function () {
      this.emit(':ask', "What can I help you with?", "How can I help?");
  },
  'AMAZON.CancelIntent': function () {
      this.emit(':tell', "Okay!");
  },
  'AMAZON.StopIntent': function () {
      this.emit(':tell', "Goodbye!");
  },
};

number = number+1;
}
exports.handler = function(event, context, callback){
  var alexa = Alexa.handler(event, context);
  alexa.appId = APP_ID;
  alexa.registerHandlers(handlers);
  alexa.execute();
};

function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {

    var prop = arr[i][propName];
    prop = prop.toUpperCase();

    if (prop == cityName) {
      return arr[i];
    }
  }
}

更新#2

在尝试了很多不同的东西之后,在 bal simpson 的帮助下,我掌握了 运行 的技能!

但是,当用户说出城市名称时,该技能仍然会出错。我的交互模型一定有错误,如下所示:

   {
        "interactionModel": {
            "languageModel": {
                "invocationName": "city picker",
                "intents": [
                    {
                        "name": "AMAZON.FallbackIntent",
                        "samples": []
                    },
                    {
                        "name": "AMAZON.CancelIntent",
                        "samples": []
                    },
                    {
                        "name": "AMAZON.HelpIntent",
                        "samples": []
                    },
                    {
                        "name": "AMAZON.StopIntent",
                        "samples": [
                            "stop"
                        ]
                    },
                    {
                        "name": "AMAZON.NavigateHomeIntent",
                        "samples": []
                    },
                    {
                        "name": "getSuggestion",
                        "slots": [],
                        "samples": [
                            "san antonio",
                            "dallas",
                            "austin"
                        ]
                    }
                ],
                "types": []
            }
        }
    }

接近!!

作为最后的努力:

这是我在 Lambda 中的 index.js。有人介意看看这个吗?

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "LaunchRequest";
  },
  handle(handlerInput) {

    console.log("LaunchRequestHandler");
    let speechText = 'Lets get you into your new home. Tell me the name of the major city you are closest to!';
    let prompt = 'Which major city are you closest to?';

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(prompt)
      .getResponse();
  }
};

const GetSuggestionIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "getSuggestion"
    );
  },
  handle(handlerInput) {
    let intent = handlerInput.requestEnvelope.request.intent;
    let city = intent.slot.city.value;

    let suggestion = getSuggestion(skillData,'city', city.toUpperCase()).suggestion;

    return handlerInput.responseBuilder
      .speak(suggestion)
      .reprompt('prompt')
      .getResponse();
  }
};

const HelpIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent"
    );
  },
  handle(handlerInput) {
    const speechText = "Try saying a city name like Austin, San Antonio, or Dallas";
    const promptText = "How can I help?";

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(promptText)
      // .withSimpleCard("City Details", speechText)
      .getResponse();
  }
};

const CancelAndStopIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      (handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.CancelIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.StopIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.PauseIntent")
    );
  },
  handle(handlerInput) {

    const speechText = `Seeya later!`;

    return (
      handlerInput.responseBuilder
        .speak(speechText)
        .withShouldEndSession(true)
        .getResponse()
    );
  }
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
    console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);

    return handlerInput.responseBuilder.getResponse();
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
      .speak('Sorry, I can\'t understand the command. Try saying a city name like Austin, San Antonio, or Dallas')
      .reprompt('Try saying a city name like Austin, San Antonio, or Dallas')
      .getResponse();
  },
};

const SystemExceptionHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type ===
      "System.ExceptionEncountered"
    );
  },
  handle(handlerInput) {
    console.log(
      `System exception encountered: ${
      handlerInput.requestEnvelope.request.reason
      }`
    );
  }
};

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    GetSuggestionIntentHandler,
    CancelAndStopIntentHandler,
    HelpIntentHandler,
    SystemExceptionHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();
  
function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {

    var prop = arr[i][propName];
    prop = prop.toUpperCase();

    if (prop == cityName) {
      return arr[i];
    }
  }
}

这是我在开发者门户中的交互模型:

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "city picker",
            "intents": [
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": [
                        "stop"
                    ]
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "getSuggestion",
                    "slots": [
                        {
                            "name": "city",
                            "type": "CITY_NAMES"
                        }
                    ],
                    "samples": [
                        "{city}"
                    ]
                }
            ],
            "types": [
                {
                    "name": "CITY_NAMES",
                    "values": [
                        {
                            "name": {
                                "value": "dallas"
                            }
                        },
                        {
                            "name": {
                                "value": "san antonio"
                            }
                        },
                        {
                            "name": {
                                "value": "austin"
                            }
                        }
                    ]
                }
            ]
        }
    }
}

好的。 alexa-sdk 已被弃用 link。要获取新的 SDK,请执行此操作。

1 - 在 Lambda 中创建一个新函数。

2 - 选择 AWS Serverless Application Repository。

3 - 选择 alexa-skills-kit-nodejs-factskill。

4 - 单击部署。部署后,单击函数,您应该会看到刚刚创建的新函数,其名称类似于 aws-serverless-repository-alexaskillskitnodejsfact-NR8HPILH8WNI。

5 - 删除代码并用此替换代码。

const Alexa = require('ask-sdk');    
const skillData = [
            {
                city: 'Austin',
                suggestion: "Austin is blahblahblahblahlshflashdfasldfha blah."
            },
            {
                city: 'San Antonio',
                suggestion: "San Antonio has blahblahblahblahlshflashdfasldfha blah."    
            },
            {
                city: 'Dallas',
                suggestion: "The Dallas metroplex is one of the hottest blahblahblahbla blahblahblahblahblahblah."
            }
        ];

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "LaunchRequest";
  },
  handle(handlerInput) {

    console.log("LaunchRequestHandler");
    let speechText = 'Tell me the name of the major city you are closest to!';
    let prompt = 'Which major city are you closest to?';

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(prompt)
      .getResponse();
  }
};

const GetSuggestionIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "getSuggestion"
    );
  },
  handle(handlerInput) {
    let intent = handlerInput.requestEnvelope.request.intent;
    let city = intent.slots.city.value;

    let suggestion = getSuggestion(skillData,'city', city.toUpperCase()).suggestion;

    return handlerInput.responseBuilder
      .speak(suggestion)
      .reprompt('prompt')
      .getResponse();
  }
};

const HelpIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent"
    );
  },
  handle(handlerInput) {
    const speechText = "Try saying a city name like Austin, San Antonio, or Dallas";
    const promptText = "How can I help?";

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(promptText)
      // .withSimpleCard("City Details", speechText)
      .getResponse();
  }
};

const CancelAndStopIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      (handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.CancelIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.StopIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.PauseIntent")
    );
  },
  handle(handlerInput) {

    const speechText = `Goodbye`;

    return (
      handlerInput.responseBuilder
        .speak(speechText)
        .withShouldEndSession(true)
        .getResponse()
    );
  }
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
    console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);

    return handlerInput.responseBuilder.getResponse();
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
      .speak('Sorry, I can\'t understand the command. Try saying a city name like Austin, San Antonio, or Dallas')
      .reprompt('Try saying a city name like Austin, San Antonio, or Dallas')
      .getResponse();
  },
};

const SystemExceptionHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type ===
      "System.ExceptionEncountered"
    );
  },
  handle(handlerInput) {
    console.log(
      `System exception encountered: ${
      handlerInput.requestEnvelope.request.reason
      }`
    );
  }
};

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    GetSuggestionIntentHandler,
    CancelAndStopIntentHandler,
    HelpIntentHandler,
    SystemExceptionHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {

    var prop = arr[i][propName];
    prop = prop.toUpperCase();

    if (prop == cityName) {
      return arr[i];
    }
  }
}

6 - 转到 developer.amazon.com 并将您的 Alexa Skill 端点更改为新的 lambda ARN。

添加插槽类型:

像这样在示例短语中指定插槽:

将您的插槽名称更改为城市:

因此,而不是 musicStations 它将是城市。确保您在广告位值中输入了三个值,如下所示:

将您的自定义槽值添加到 CITY_NAMES:

如果你做对了,你的交互模型应该是这样的:

                "name": "getSuggestion",
                "slots": [
                    {
                        "name": "city",
                        "type": "CITY_NAMES"
                    }
                ],
                "samples": [
                    "city name is {city}",
                    "{city}"
                ]

测试 Lambda 代码

在下拉菜单中,选择 'configure test events'。

使用 JSON 从您的开发人员测试门户创建新的测试事件,应该如下所示。

{
"version": "1.0",
"session": {
    "new": true,
    "sessionId": "amzn1.echo-api.session.XXXXXX",
    "application": {
        "applicationId": "amzn1.ask.skill.XXXXXX"
    },
    "user": {
        "userId": "amzn1.ask.account.XXXXXX"
    }
},
"context": {
    "AudioPlayer": {
        "playerActivity": "IDLE"
    },
    "System": {
        "application": {
            "applicationId": "amzn1.ask.skill.XXXXXX"
        },
        "user": {
            "userId": "amzn1.ask.account.XXXXXX"
        },
        "device": {
            "deviceId": "amzn1.ask.device.XXXXXX",
            "supportedInterfaces": {
                "AudioPlayer": {}
            }
        },
        "apiEndpoint": "https://api.eu.amazonalexa.com",
        "apiAccessToken": "ACCESS_TOKEN"
    },
},
"request": {
    "type": "IntentRequest",
    "requestId": "amzn1.echo-api.request.XXXX",
    "timestamp": "2018-12-03T20:28:29Z",
    "locale": "en-IN",
    "intent": {
        "name": "PlayRadioIntent",
        "confirmationStatus": "NONE",
        "slots": {
            "musicStation": {
                "name": "musicStation",
                "value": "classic rock",
                "resolutions": {
                    "resolutionsPerAuthority": [
                        {
                            "authority": "amzn1.er-authority.XXXX.RadioStations",
                            "status": {
                                "code": "ER_SUCCESS_MATCH"
                            },
                            "values": [
                                {
                                    "value": {
                                        "name": "Classic Rock",
                                        "id": "b8a5bd97a8a02691f9f81dcfb12184dd"
                                    }
                                }
                            ]
                        }
                    ]
                },
                "confirmationStatus": "NONE",
                "source": "USER"
            }
        }
    }
}

点击测试按钮

检查日志

测试结果是这样的吗?要查看日志,请单击 logs。它可能有其他错误详细信息。