基于AWS Lambda的Alexa意图调用Yummly API异步函数问题
搞定Alexa + Lambda + Yummly API的食谱推荐(给Python开发者的JS指南)
嘿,作为经常折腾Alexa技能和第三方API的开发者,我太懂从Python转JavaScript的别扭感了!我来帮你把这段RecommendationIntent的代码补全,并且解释清楚关键步骤~
先看你现有代码的作用
你已经写了槽位收集的核心逻辑,这段代码是让Alexa自动引导用户补全所有必填的槽位信息(比如食材、菜系、饮食限制),收集完成后会打印槽位内容,但还缺调用Yummly API和把结果返回给Alexa的核心环节。先把你给出的代码片段格式化一下:
"RecommendationIntent": function () { // delegate to Alexa to collect all the required slots let filledSlots = delegateSlotCollection.call(this); if (!filledSlots) { return; } console.log("filled slots: " + JSON.stringify(filledSlots)); // 这里就是要加API调用和结果返回的地方 }
补全完整代码步骤
1. 初始化Yummly客户端
首先要确保你已经安装了ws-yummly库,本地运行npm install ws-yummly(之后打包Lambda要带上node_modules文件夹),然后在代码顶部引入并初始化:
const Yummly = require('ws-yummly'); // 替换成你在Yummly开发者平台申请的App ID和Key const yummlyClient = new Yummly({ app_id: '你的YUMMLY_APP_ID', app_key: '你的YUMMLY_API_KEY' });
2. 完善Intent逻辑
这里我提供两种写法:一种是JS传统的Promise链式调用,另一种是更接近Pythonasync/await的写法,你可以选更顺手的:
写法一:Promise链式调用
"RecommendationIntent": function () { // 收集槽位 let filledSlots = delegateSlotCollection.call(this); if (!filledSlots) { return; } console.log("filled slots: " + JSON.stringify(filledSlots)); // 从槽位提取搜索参数(根据你在Alexa控制台配置的槽位名称调整) const searchParams = { q: filledSlots.Ingredient.value, // 用户说的食材,比如"鸡肉" allowedCuisine: { 'cuisine': [filledSlots.Cuisine.value] }, // 比如"中式" allowedDiet: { 'diet': [filledSlots.DietaryRestriction.value] } // 比如"素食" }; // 调用Yummly搜索API yummlyClient.search(searchParams) .then(apiResponse => { // 处理返回结果,比如取前3个食谱 const topRecipes = apiResponse.matches.slice(0, 3); // 构造给Alexa的语音回复 let speechContent = "我给你推荐这几个食谱:"; topRecipes.forEach((recipe, idx) => { speechContent += `第${idx+1}个是${recipe.recipeName},`; }); // 调整语句更自然,去掉末尾逗号 speechContent = speechContent.slice(0, -1) + "。"; // 返回结果给用户,同时监听后续请求 this.response.speak(speechContent).listen("还需要其他食谱推荐吗?"); this.emit(':responseReady'); }) .catch(error => { // 处理API调用错误 console.error("Yummly API调用失败:", error); this.response.speak("抱歉,现在无法获取食谱推荐,请稍后再试。"); this.emit(':responseReady'); }); }
写法二:Async/Await(更像Python的异步风格)
如果你习惯Python的async/await,可以把Intent改成异步函数,代码可读性更高:
"RecommendationIntent": async function () { // 收集槽位 let filledSlots = delegateSlotCollection.call(this); if (!filledSlots) { return; } console.log("filled slots: " + JSON.stringify(filledSlots)); // 提取搜索参数 const searchParams = { q: filledSlots.Ingredient.value, allowedCuisine: { 'cuisine': [filledSlots.Cuisine.value] }, allowedDiet: { 'diet': [filledSlots.DietaryRestriction.value] } }; try { // 等待API返回结果 const apiResponse = await yummlyClient.search(searchParams); const topRecipes = apiResponse.matches.slice(0, 3); let speechContent = "我给你推荐这几个食谱:"; topRecipes.forEach((recipe, idx) => { speechContent += `第${idx+1}个是${recipe.recipeName},`; }); speechContent = speechContent.slice(0, -1) + "。"; this.response.speak(speechContent).listen("还需要其他食谱推荐吗?"); this.emit(':responseReady'); } catch (error) { console.error("Yummly API调用失败:", error); this.response.speak("抱歉,现在无法获取食谱推荐,请稍后再试。"); this.emit(':responseReady'); } }
给Python开发者的关键注意事项
- Lambda打包:Lambda需要包含所有依赖,所以本地安装
ws-yummly后,要把项目文件夹(包括node_modules)打包成ZIP文件上传到Lambda控制台。 - 权限配置:确保你的Lambda执行角色有互联网访问权限(因为要调用Yummly的外部API),如果Lambda在VPC里,还需要配置NAT网关。
- 槽位配置:在Alexa开发者控制台里,给槽位配置合适的类型(比如用内置的
AMAZON.Cuisine类型识别菜系),这样Alexa能更准确理解用户的语音输入。 - JS异步逻辑:JS的异步操作和Python差异很大,
async/await是最接近Python异步写法的方式,建议优先用这种风格,减少回调地狱的困扰。
内容的提问来源于stack exchange,提问作者Teckrio
相关产品推荐
相关产品推荐

