如何指定要使用的 API 数据?
How do I specify which API data I want to use?
我正在开发一项 Alexa 技能(使用 v2 和 javascript),我正在尝试向美国农业部 API 拨打 API GET
电话。
此时我从 here and I'm using the USDA API example from here copy/pasted(有一些小的改动)。作为尝试让连接正常工作,return 任何证明它有效的东西。
我目前收到的错误是: Error handled: TypeError: Cannot read property 'generalSearchInput' of undefined at Object.handle (/var/task/index.js:39:32)
at process._tickCallback (internal/process/next_tick.js:68:7)
在错误发生之前,我得到了 return of: 美国农业部 API 中关于 Cottage Cheese 的每个条目,即 I.E. 与 console.log(response)
相比 太多了。我只想要第一个,甚至只是名字。
控制台日志告诉我,我正在接收从呼叫返回的数据,所以我知道它正在工作。我的问题是:如何将 speechOutput
设置为我需要的特定信息,而不是 returned 的整个 API 对象?
我要找的speechOutput
应该是: Cottage Cheese
我收到的响应是: Alexa 的输出说:
Sorry, I had trouble doing what you asked. Please try again
index.js
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
const speakOutput = 'Welcome to food points! What food would you like to know about?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const FoodPointsIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'FoodPointsIntent';
},
async handle(handlerInput) {
console.log("THIS.EVENT = " + JSON.stringify(this.event));
var speakOutput = 'Sorry, there was an error';
//var https = require('https');
const { requestEnvelope } = handlerInput;
const userInput = Alexa.getSlotValue(requestEnvelope, 'FoodQuery');
const response = await httpGet();
console.log(response);
/*
const food = userInput;
speakOutput = food;
*/
speakOutput = response.value.generalSearchInput;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const TestIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'TestIntent';
},
handle(handlerInput) {
console.log("THIS.EVENT = " + JSON.stringify(this.event));
var speakOutput = 'Sorry, there was an error';
const { requestEnvelope } = handlerInput;
const userInput = Alexa.getSlotValue(requestEnvelope, 'TestQuery');
const food = userInput;
speakOutput = food;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
function httpGet() {
return new Promise(((resolve, reject) => {
var options = {
host: 'api.nal.usda.gov',
port: 443,
path: '/fdc/v1/foods/search?api_key=DEMO_KEY&query=Cheddar%20Cheese',
method: 'GET',
};
var https = require('https');
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();
}));
}
/****************************REMEMBER TO UPDATE THIS*************************/
const HelpIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speakOutput = 'You can say hello to me! How can I help?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
|| Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speakOutput = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
},
handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
const speakOutput = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.stack}`);
const speakOutput = `Sorry, I had trouble doing what you asked. Please try again.`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
FoodPointsIntentHandler,
TestIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
我想通了。希望这可以帮助可能被卡住的人。
我错误地调用了 API 数据。
完成我需要的代码
var nvArray = [];
for(var i = 0; i < response.foods[0].foodNutrients.length; i++) {
var nvArrayString = [response.foods[0].foodNutrients[i].nutrientName] + '';
var nvShortString = nvArrayString.split(',', 1);
nvArray.push(nvShortString);
}
var nvArraySpeakOutputString = nvArray.join();
修复我的错误的实际代码
response.foods[0].foodNutrients[i].nutrientName
我正在查看提供给我的数据的错误部分,因此调用了一些不存在的东西,即 response.value.generalSearchInput
。
可能有用的其他信息
使用 nvArray
以便我可以将数据中的多个变量放在一个地方(使用 push
和 pop
)。
这允许我在每次循环运行时将数据 split
分成更短的部分(用于防止输出成为每个项目的文本墙)。
nvArraySpeakOutputString
是 nvArray
join
的组合,允许 Alexa 将所有内容作为一个变量来表达,让我不必输入
varA + '. next ' + varB
依此类推。
无论如何,希望这对某些人有所帮助!
我正在开发一项 Alexa 技能(使用 v2 和 javascript),我正在尝试向美国农业部 API 拨打 API GET
电话。
此时我从 here and I'm using the USDA API example from here copy/pasted(有一些小的改动)。作为尝试让连接正常工作,return 任何证明它有效的东西。
我目前收到的错误是: Error handled: TypeError: Cannot read property 'generalSearchInput' of undefined at Object.handle (/var/task/index.js:39:32)
at process._tickCallback (internal/process/next_tick.js:68:7)
在错误发生之前,我得到了 return of: 美国农业部 API 中关于 Cottage Cheese 的每个条目,即 I.E. 与 console.log(response)
相比 太多了。我只想要第一个,甚至只是名字。
控制台日志告诉我,我正在接收从呼叫返回的数据,所以我知道它正在工作。我的问题是:如何将 speechOutput
设置为我需要的特定信息,而不是 returned 的整个 API 对象?
我要找的speechOutput
应该是: Cottage Cheese
我收到的响应是: Alexa 的输出说:
Sorry, I had trouble doing what you asked. Please try again
index.js
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
const speakOutput = 'Welcome to food points! What food would you like to know about?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const FoodPointsIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'FoodPointsIntent';
},
async handle(handlerInput) {
console.log("THIS.EVENT = " + JSON.stringify(this.event));
var speakOutput = 'Sorry, there was an error';
//var https = require('https');
const { requestEnvelope } = handlerInput;
const userInput = Alexa.getSlotValue(requestEnvelope, 'FoodQuery');
const response = await httpGet();
console.log(response);
/*
const food = userInput;
speakOutput = food;
*/
speakOutput = response.value.generalSearchInput;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const TestIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'TestIntent';
},
handle(handlerInput) {
console.log("THIS.EVENT = " + JSON.stringify(this.event));
var speakOutput = 'Sorry, there was an error';
const { requestEnvelope } = handlerInput;
const userInput = Alexa.getSlotValue(requestEnvelope, 'TestQuery');
const food = userInput;
speakOutput = food;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
function httpGet() {
return new Promise(((resolve, reject) => {
var options = {
host: 'api.nal.usda.gov',
port: 443,
path: '/fdc/v1/foods/search?api_key=DEMO_KEY&query=Cheddar%20Cheese',
method: 'GET',
};
var https = require('https');
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();
}));
}
/****************************REMEMBER TO UPDATE THIS*************************/
const HelpIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speakOutput = 'You can say hello to me! How can I help?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
|| Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speakOutput = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
},
handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
const speakOutput = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.stack}`);
const speakOutput = `Sorry, I had trouble doing what you asked. Please try again.`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
FoodPointsIntentHandler,
TestIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
我想通了。希望这可以帮助可能被卡住的人。
我错误地调用了 API 数据。
完成我需要的代码
var nvArray = [];
for(var i = 0; i < response.foods[0].foodNutrients.length; i++) {
var nvArrayString = [response.foods[0].foodNutrients[i].nutrientName] + '';
var nvShortString = nvArrayString.split(',', 1);
nvArray.push(nvShortString);
}
var nvArraySpeakOutputString = nvArray.join();
修复我的错误的实际代码
response.foods[0].foodNutrients[i].nutrientName
我正在查看提供给我的数据的错误部分,因此调用了一些不存在的东西,即 response.value.generalSearchInput
。
可能有用的其他信息
使用nvArray
以便我可以将数据中的多个变量放在一个地方(使用 push
和 pop
)。
这允许我在每次循环运行时将数据 split
分成更短的部分(用于防止输出成为每个项目的文本墙)。
nvArraySpeakOutputString
是 nvArray
join
的组合,允许 Alexa 将所有内容作为一个变量来表达,让我不必输入
varA + '. next ' + varB
依此类推。
无论如何,希望这对某些人有所帮助!