调用OpenWeather API无法读取数据 触发undefined属性报错
问题表现
接入OpenWeather API做天气查询功能时,输入城市名发起请求就抛出cannot read undefined (reading '0')错误,无法正常读取API返回数据,原实现代码如下:
app.post("/",function(req,res){ const city=req.body.CityName; const url="https://api.openweathermap.org/data/2.5/weather?q="+city+"&units=metric&appid=c6d442adf9595680af9098f5a91497a4"; https.get(url,function(response){ response.on("data",function(data){ const weather_data=JSON.parse(data); const des=weather_data.weather[1].description; const temp=weather_data.main.temp; const icon=weather_data.weather[0].icon; const imageURL=" http://openweathermap.org/img/wn/"+ icon +"@2x.png"; res.write("<p>Temperature of "+req.body.CityName+" is "+ temp +" degrees with "+ des+"</p>"); res.write("<img src=" + imageURL + ">"); res.send(); }) }) })
错误根因
- 数组下标使用错误:OpenWeather接口返回的
weather是天气描述数组,常规查询场景下该数组仅存在1个元素,数组下标从0开始计数。原代码读取天气描述时用了weather_data.weather[1],访问了不存在的第二个数组元素,拿到undefined后再读取description属性直接触发类型错误。如果遇到城市名无效、密钥错误等接口异常场景,返回结构中甚至不存在weather字段,此时连weather[0]的读取都会抛出同类错误。 - 响应接收逻辑错误:Node.js的HTTP响应
data事件是分块触发的,单次回调拿到的data可能只是响应内容的片段,直接对片段做JSON.parse大概率会解析失败。
修复方案
- 拼接所有响应数据块,在
end事件触发后再做JSON解析 - 先校验接口返回的状态码,确认请求成功后再读取业务字段
- 修正
weather数组的读取下标,统一从下标0取数据 - 增加必要的错误兜底,避免接口异常时服务崩溃
修复后可参考的代码如下:
app.post("/", function(req, res) { const city = req.body.CityName; const url = "https://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=metric&appid=c6d442adf9595680af9098f5a91497a4"; https.get(url, function(response) { // 拼接所有响应数据块 let rawData = ''; response.on('data', (chunk) => { rawData += chunk; }); response.on('end', () => { try { const weather_data = JSON.parse(rawData); // 校验接口返回状态,OpenWeather成功返回时cod字段为200 if (weather_data.cod !== 200) { return res.send(`<p>查询失败:${weather_data.message}</p>`); } // 统一从weather数组下标0读取数据 const des = weather_data.weather[0].description; const temp = weather_data.main.temp; const icon = weather_data.weather[0].icon; const imageURL = "http://openweathermap.org/img/wn/" + icon + "@2x.png"; res.write("<p>Temperature of " + req.body.CityName + " is " + temp + " degrees with " + des + "</p>"); res.write("<img src=" + imageURL + ">"); res.send(); } catch (err) { res.send(`<p>数据解析失败,请稍后重试</p>`); } }) }) })
内容的提问来源于stack exchange,提问作者Macfros
相关产品推荐
相关产品推荐

