Lambda实现Alexa Skill调用REST API后返回空及speechOutput错误求助
问题排查与解决:
speechOutput.trim is not a function 错误 你遇到的这个错误,核心原因是异步请求的回调逻辑没有正确返回Alexa响应,导致你的handle函数实际上没有返回任何有效内容,Alexa拿到的响应是空的,自然就会报speechOutput.trim is not a function(因为根本找不到speechOutput这个属性)。
具体分析你的代码问题:
你用的Request.get是典型的回调式异步方法,当你的handle函数执行到Request.get时,会立刻继续往下走,不会等待回调函数执行完毕。但你把响应构建代码return handlerInput.responseBuilder...写在了回调函数里——这个return只是回调函数的返回值,不是handle函数的返回值!所以handle函数最终返回的是undefined,Alexa接收不到合法的响应,就会抛出这个错误。
解决方案:改用异步/同步的方式处理请求
要解决这个问题,你需要把异步请求改成可以等待的形式,比如用async/await配合Promise化的请求方法。这里有两种常用的修改方式:
方式1:用util.promisify包装Request.get
Node.js内置的util模块可以把回调式的方法转换成Promise形式,这样就能用await等待请求完成:
const util = require('util'); const Request = require('request'); const getRequest = util.promisify(Request.get); // 包装成Promise const HelloWorldIntentHandler = { canHandle(handlerInput) { console.log("HelloWorldIntentHandler 1: "); return handlerInput.requestEnvelope.request.type === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent'; }, async handle(handlerInput) { // 标记为async函数 console.log("HelloWorldIntentHandler 2"); let speechText = 'Hello World'; try { const response = await getRequest(url); // 等待请求完成 const data = JSON.parse(response.body); const result = data.records.totalNum; if (result > 0) { speechText = `There are ${result} matches`; } else { speechText = "ERROR"; } } catch (error) { // 处理请求错误,比如网络问题、API返回异常 speechText = "Sorry, I couldn't get the data right now."; console.error('Request error:', error); } // 这里的return是handle函数的返回值,能正确传给Alexa return handlerInput.responseBuilder .speak(speechText) .withSimpleCard('Hello World', speechText) .getResponse(); }, };
方式2:改用支持Promise的请求库(比如axios)
如果你不想自己包装,直接用axios这类原生支持Promise的库会更简洁:
首先安装axios:
npm install axios
然后修改代码:
const axios = require('axios'); const HelloWorldIntentHandler = { canHandle(handlerInput) { console.log("HelloWorldIntentHandler 1: "); return handlerInput.requestEnvelope.request.type === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent'; }, async handle(handlerInput) { console.log("HelloWorldIntentHandler 2"); let speechText = 'Hello World'; try { const response = await axios.get(url); const data = response.data; const result = data.records.totalNum; if (result > 0) { speechText = `There are ${result} matches`; } else { speechText = "ERROR"; } } catch (error) { speechText = "Sorry, I couldn't get the data right now."; console.error('Request error:', error); } return handlerInput.responseBuilder .speak(speechText) .withSimpleCard('Hello World', speechText) .getResponse(); }, };
额外提示:
- 一定要加上错误捕获(
try/catch),避免因为API请求失败导致Skill崩溃; - 用模板字符串(
`There are ${result} matches`)比字符串拼接更简洁易读; - 确认你的
url变量已经正确定义,否则请求也会失败哦。
内容的提问来源于stack exchange,提问作者user1366265
相关产品推荐
相关产品推荐

