求助:Node.js Lambda Handler发起HTTP请求获取JSON结果的示例
问题分析与解决方案
原代码核心问题
你的代码运行跳转到通用处理程序,主要是以下几个原因:
- 异步操作未正确处理:
request是回调风格的异步库,但你直接同步返回了Alexa响应,导致API请求还没完成就返回了初始的speakOutput,甚至错误处理代码存在语法错误(speakOutput = "xxx".speak(speakOutput)属于无效链式调用)。 - HTTP方法错误:
api.weather.gov/points接口是GET请求,你误用了POST方法,还发送了不必要的JSON参数,导致API返回错误。 - 缺少强制请求头:该气象API要求请求头必须包含
User-Agent(标识你的应用),否则会返回403拒绝访问。 - 使用已弃用库:
request库已停止维护,存在安全隐患,建议替换为现代HTTP客户端。
可用Node.js HTTP请求示例(基于Axios,异步/await风格)
首先确保Lambda部署包或层包含axios(可通过npm install axios安装后打包):
const axios = require('axios'); const TornadoWarningIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'TornadoWarningIntent'; }, async handle(handlerInput) { let speakOutput = '获取气象数据失败,请稍后再试'; try { // 调用气象API,使用正确的GET方法和强制请求头 const response = await axios.get('https://api.weather.gov/points/38.8894,-77.0352', { headers: { 'User-Agent': '你的Alexa技能名称/1.0 (your-email@example.com)' // 必须替换为你的信息 } }); // 解析API返回的JSON数据(示例:提取经纬度) const pointData = response.data; speakOutput = `已获取当前定位的气象数据:纬度${pointData.properties.latitude},经度${pointData.properties.longitude}。如需龙卷风预警详情,请说继续。`; } catch (error) { console.error('API请求错误:', error); speakOutput = '获取气象数据时出现错误,请稍后再试'; } return handlerInput.responseBuilder .speak(speakOutput) .reprompt('请说继续获取详情,或者重复当前内容') .getResponse(); } };
基于Node.js内置https模块的示例(无需额外依赖)
如果不想引入第三方库,可使用Node.js原生https模块:
const https = require('https'); const TornadoWarningIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'TornadoWarningIntent'; }, handle(handlerInput) { return new Promise((resolve) => { let speakOutput = '获取气象数据失败,请稍后再试'; const options = { hostname: 'api.weather.gov', path: '/points/38.8894,-77.0352', method: 'GET', headers: { 'User-Agent': '你的Alexa技能名称/1.0 (your-email@example.com)' } }; const req = https.request(options, (res) => { let rawData = ''; res.on('data', (chunk) => rawData += chunk); res.on('end', () => { try { const pointData = JSON.parse(rawData); speakOutput = `已获取当前定位的气象数据:纬度${pointData.properties.latitude},经度${pointData.properties.longitude}。如需龙卷风预警详情,请说继续。`; } catch (parseError) { console.error('JSON解析错误:', parseError); } const response = handlerInput.responseBuilder .speak(speakOutput) .reprompt('请说继续获取详情,或者重复当前内容') .getResponse(); resolve(response); }); }); req.on('error', (error) => { console.error('请求错误:', error); const response = handlerInput.responseBuilder .speak(speakOutput) .getResponse(); resolve(response); }); req.end(); }); } };
你遗漏的关键步骤
- 异步响应处理:Alexa的Intent Handler必须通过返回Promise或使用
async/await来处理异步操作,否则会在API请求完成前就返回默认响应。 - 匹配API要求的请求方法:必须根据API文档使用正确的HTTP方法(GET/POST等),不能随意混用。
- 添加强制请求头:部分公共API会验证请求头,必须按要求提供
User-Agent等标识信息。 - 完整错误捕获:必须捕获异步请求中的所有错误(网络错误、API返回错误状态码、JSON解析错误等),避免未处理的异常导致Lambda报错,触发Alexa的通用错误处理。
- 替换弃用库:停止使用已维护的
request库,改用axios、node-fetch或原生https模块。
内容的提问来源于stack exchange,提问作者DanL
相关产品推荐
相关产品推荐

