JavaScript天气APP:async函数processFormat未完成时showResults已执行
为什么await processFormat后仍无法获取到Fetch请求的数据?
我正在使用JavaScript Fetch API开发天气预报应用,希望在showResults函数中使用processFormat函数返回的数据,但无法实现——showResults函数总是在processFormat函数执行完成前就运行。我尝试在showResults函数第一行添加await processFormat(range);但没有效果,输出中的对象和数组都是空的,请问这是为什么?
const processFormat = async (range) => { let getCityUrl = `http://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=${limit}&appid=${apiKey}`; //resultStates.length = 0; fetch(getCityUrl) .then((response) => { return response.json(); }) .then((data) => { data.forEach((item) => { console.log(item); resultStates.push(item.state); resultObj[item.state] = { 'lat': item['lat'], 'lon': item['lon'] }; }); }) .catch(rejected => { console.log(rejected); }) console.log(resultObj); }; //... const showResults = async (range) => { await processFormat(range); for (let i=0; i<Object.keys(resultObj).length; i++) { resultStates.push(Object.keys(resultObj)[i]); } console.log(`resultStates: ${resultStates}`) if (resultStates.length === 0) { resultSection.textContent = `Failed to find your city: ${city}. Try another city`; setTimeout(() => { resultSection.textContent = ''; clickedSearch = 0; }, 5000); } else { //... } };
问题根源
processFormat未真正等待异步操作:虽然给processFormat标记了async,但内部的fetch调用既没有被await,也没有返回Promise链。这导致processFormat会立刻返回一个已完成的Promise,showResults里的await根本不会等待fetch请求和后续数据处理完成。- 全局变量的时序冲突:你依赖的
resultObj和resultStates是全局变量,它们的填充逻辑在fetch的回调函数中——这个回调要等网络请求完成后才会执行,而showResults的代码会在processFormat“假结束”后立刻运行,此时回调还没执行,全局变量自然是空的。
解决方法
1. 修复processFormat,让它真正等待异步操作
用await处理fetch和响应解析,同时直接返回处理好的数据(避免依赖全局变量):
const processFormat = async (range) => { const getCityUrl = `http://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=${limit}&appid=${apiKey}`; try { // 等待fetch请求完成 const response = await fetch(getCityUrl); // 等待响应解析为JSON const data = await response.json(); const resultObj = {}; const resultStates = []; data.forEach((item) => { console.log(item); resultStates.push(item.state); resultObj[item.state] = { lat: item.lat, lon: item.lon }; }); console.log(resultObj); // 返回处理好的结果 return { resultObj, resultStates }; } catch (err) { console.log(err); // 抛出错误让调用方处理 throw err; } };
2. 修改showResults,直接接收返回的数据
不再依赖全局变量,使用processFormat返回的结果完成后续逻辑:
const showResults = async (range) => { try { // 等待processFormat完成并获取返回的数据 const { resultObj, resultStates } = await processFormat(range); console.log(`resultStates: ${resultStates}`); if (resultStates.length === 0) { resultSection.textContent = `Failed to find your city: ${city}. Try another city`; setTimeout(() => { resultSection.textContent = ''; clickedSearch = 0; }, 5000); } else { // 此处编写后续处理逻辑,直接使用resultObj和resultStates即可 } } catch (err) { // 处理请求失败的情况 resultSection.textContent = `Request failed: ${err.message}`; setTimeout(() => { resultSection.textContent = ''; clickedSearch = 0; }, 5000); } };
额外提示
- 尽量避免用全局变量传递异步操作的结果,直接返回数据能让代码逻辑更清晰,减少状态冲突风险。
- 添加
try/catch捕获错误,能更优雅地处理请求失败的情况,提升用户体验。
内容的提问来源于stack exchange,提问作者Liza
相关产品推荐
相关产品推荐

