我正在开发一个Alexa技能,引用自:Alexa NodeJS Dynamodb skill,在获取这些问题的所有插槽值后,向用户询问他们想要添加的配方以及一些有关它的更多信息,它首先检查(在DynamoDB上执行get操作)是否项已存在,否则添加该项。
以下是仅一个Intent的代码段:
const alexaSDK = require('alexa-sdk');
const awsSDK = require('aws-sdk');
const {promisify} = require('es6-promisify');
const recipesTable = 'Recipes';
const docClient = new awsSDK.DynamoDB.DocumentClient();
// convert callback style functions to promises
const dbScan = promisify(docClient.scan, docClient);
const dbGet = promisify(docClient.get, docClient);
const dbPut = promisify(docClient.put, docClient);
const dbDelete = promisify(docClient.delete, docClient);
const instructions = `Welcome to Recipe Organizer<break strength="medium" />
The following commands are available: add recipe, get
recipe,get all recipes, get a random recipe, and delete recipe. What would
you like to do?`;
const handlers = {
/**
* Triggered when the user says "Alexa, open Recipe Organizer.
*/
'LaunchRequest'() {
this.emit(':ask', instructions);
},
/**
* Adds a recipe to the current user's saved recipes.
* Slots: RecipeName, RecipeLocation, LongOrQuick
*/
'AddRecipeIntent'() {
const { userId } = this.event.session.user;
const { slots } = this.event.request.intent;
// prompt for slot values and request a confirmation for each
// RecipeName
if (!slots.RecipeName.value) {
const slotToElicit = 'RecipeName';
const speechOutput = 'What is the name of the recipe?';
const repromptSpeech = 'Please tell me the name of the recipe';
return this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
}
else if (slots.RecipeName.confirmationStatus !== 'CONFIRMED') {
if (slots.RecipeName.confirmationStatus !== 'DENIED') {
// slot status: unconfirmed
const slotToConfirm = 'RecipeName';
const speechOutput = `The name of the recipe is ${slots.RecipeName.value}, correct?`;
const repromptSpeech = speechOutput;
return this.emit(':confirmSlot', slotToConfirm, speechOutput, repromptSpeech);
}
// slot status: denied -> reprompt for slot data
const slotToElicit = 'RecipeName';
const speechOutput = 'What is the name of the recipe you would like to add?';
const repromptSpeech = 'Please tell me the name of the recipe';
return this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
}
// RecipeLocation
if (!slots.RecipeLocation.value) {
const slotToElicit = 'RecipeLocation';
const speechOutput = 'Where can the recipe be found?';
const repromptSpeech = 'Please give me a location where the recipe can be found.';
return this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
}
else if (slots.RecipeLocation.confirmationStatus !== 'CONFIRMED') {
if (slots.RecipeLocation.confirmationStatus !== 'DENIED') {
// slot status: unconfirmed
const slotToConfirm = 'RecipeLocation';
const speechOutput = `The recipe location is ${slots.RecipeLocation.value}, correct?`;
const repromptSpeech = speechOutput;
return this.emit(':confirmSlot', slotToConfirm, speechOutput, repromptSpeech);
}
// slot status: denied -> reprompt for slot data
const slotToElicit = 'RecipeLocation';
const speechOutput = 'Where can the recipe be found?';
const repromptSpeech = 'Please give me a location where the recipe can be found.';
return this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
}
// LongOrQuick
if (!slots.LongOrQuick.value) {
const slotToElicit = 'LongOrQuick';
const speechOutput = 'Is this a quick or long recipe to make?';
const repromptSpeech = 'Is this a quick or long recipe to make?';
return this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
}
else if (slots.LongOrQuick.confirmationStatus !== 'CONFIRMED') {
if (slots.LongOrQuick.confirmationStatus !== 'DENIED') {
// slot status: unconfirmed
const slotToConfirm = 'LongOrQuick';
const speechOutput = `This is a ${slots.LongOrQuick.value} recipe, correct?`;
const repromptSpeech = speechOutput;
return this.emit(':confirmSlot', slotToConfirm, speechOutput, repromptSpeech);
}
// slot status: denied -> reprompt for slot data
const slotToElicit = 'LongOrQuick';
const speechOutput = 'Is this a quick or long recipe to make?';
const repromptSpeech = 'Is this a quick or long recipe to make?';
return this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
}
// all slot values received and confirmed, now add the record to DynamoDB
const name = slots.RecipeName.value;
const location = slots.RecipeLocation.value;
const isQuick = slots.LongOrQuick.value.toLowerCase() === 'quick';
const dynamoParams = {
TableName: recipesTable,
Item: {
Name: name,
UserId: userId,
Location: location,
IsQuick: isQuick
}
};
const checkIfRecipeExistsParams = {
TableName: recipesTable,
Key: {
Name: name,
UserId: userId
}
};
console.log('Attempting to add recipe', dynamoParams);
// query DynamoDB to see if the item exists first
dbGet(checkIfRecipeExistsParams)
.then(data => {
console.log('Get item succeeded', data);
const recipe = data.Item;
if (recipe) {
const errorMsg = `Recipe ${name} already exists!`;
this.emit(':tell', errorMsg);
throw new Error(errorMsg);
}
else {
// no match, add the recipe
return dbPut(dynamoParams);
}
})
.then(data => {
console.log('Add item succeeded', data);
this.emit(':tell', `Recipe ${name} added!`);
})
.catch(err => {
console.error(err);
});
},
但是我得到 TypeError:无法读取未定义的属性'getItem'。
以下是执行堆栈的完整日志: AWS Console Log
PS:我正在使用Apex将我的代码部署到AWS Lambda,并且我已经为IAM角色提供了DYNAMODBFULLACCESS。