为何自定义getWeatherData函数返回undefined而非预期数组?
解决异步函数返回undefined的问题
嘿,这个坑我踩过好多次!你遇到的是异步JavaScript的经典问题——fetch是异步操作,你的getWeatherData函数根本没有返回任何东西,所以外部调用它的时候自然拿到undefined。
问题根源
你写的.then里的return只是给那个回调函数用的,不是getWeatherData函数的返回值。fetch发起请求后,getWeatherData函数会立刻执行完(因为异步操作不会阻塞代码),此时函数没有返回值,所以values就是undefined。等fetch请求完成后,.then里的代码才会跑,但这时候外部的console.log(values)早就执行完了。
修复方案
我们需要让getWeatherData返回整个fetch的Promise链,这样外部就能通过.then或者async/await来获取异步操作的结果。
方案1:用Promise链式调用(保持原风格)
let city = "London" // 外部通过.then接收结果 getWeatherData(city, "en") .then(values => { console.log(values); // 这里就能拿到正确的数组了 }) .catch(err => console.error("获取数据失败:", err)); function getWeatherData(city, lang) { // 关键:返回整个fetch的Promise链 return fetch(`http://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=1&appid={My_API_Key}`) .then(response => { // 新增:检查请求是否成功(比如404、500这些情况) if (!response.ok) { throw new Error(`请求失败,状态码: ${response.status}`); } return response.json(); }) .then(data => { // 新增:检查API是否返回有效数据 if (!data || data.length === 0) { throw new Error("未找到该城市的信息"); } // 用可选链避免local_names中没有对应lang的情况,同时fallback到默认城市名 const cityName = data[0]['local_names']?.[lang] || data[0]['name']; const cityCountryname = data[0]['country']; const cityLat = data[0]['lat']; const cityLon = data[0]['lon']; return [cityCountryname, cityName, cityLat, cityLon]; }) .catch(err => { console.error("内部错误:", err); throw err; // 把错误抛出去,让外部能捕获处理 }); }
方案2:用async/await(更易读的现代写法)
如果你的环境支持ES2017+,推荐用async/await,异步代码看起来像同步的,可读性更高:
// 把函数标记为async async function getWeatherData(city, lang) { try { const response = await fetch(`http://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=1&appid={My_API_Key}`); if (!response.ok) { throw new Error(`请求失败,状态码: ${response.status}`); } const data = await response.json(); if (!data || data.length === 0) { throw new Error("未找到该城市的信息"); } const cityName = data[0]['local_names']?.[lang] || data[0]['name']; const cityCountryname = data[0]['country']; const cityLat = data[0]['lat']; const cityLon = data[0]['lon']; return [cityCountryname, cityName, cityLat, cityLon]; } catch (err) { console.error("获取数据出错:", err); throw err; } } // 调用时需要在async函数里用await (async () => { let city = "London"; try { const values = await getWeatherData(city, "en"); console.log(values); } catch (err) { console.error("外部处理错误:", err); } })();
几个额外的小建议
- 永远要处理异步操作的错误,包括网络失败、API返回错误状态码、数据为空这些情况
- 用模板字符串代替字符串拼接,代码更干净(比如
${city}) - 用可选链
?.避免访问不存在的属性时抛出错误(比如data[0]['local_names']?.[lang]) - 如果API返回的
local_names里没有你指定的语言,可以fallback到默认的name字段,提升用户体验
内容的提问来源于stack exchange,提问作者nexab
相关产品推荐
相关产品推荐

