Promise链式调用问题:通过OpenWeatherMap API获取当前及5天天气
问题排查与修复方案
核心问题分析
- 错误访问
weekWeatherUrl:原代码中data.weekWeatherUrl完全错误,data是第一个API返回的天气数据对象,不存在weekWeatherUrl字段,应直接使用函数内预定义的weekWeatherUrl变量。 this指向丢失:.then()的普通函数回调中,this指向并非weatherData对象,导致调用this.unveilWeather时会报错。可改用箭头函数,或提前保存this引用。- 函数名不匹配:对象内定义的方法是
getWeatherInfo,但调用时用了getCurrentWeatherInfo,导致找不到函数抛出错误。 - 未处理双API数据:原代码仅处理了第二个API的返回结果,没有分别处理当前天气和5天预报的逻辑。
async/await使用误区:对象方法可直接声明为async function,通过await简化异步请求的处理流程。
修复后的代码(推荐async/await版本,更易读)
// 先替换为你的OpenWeatherMap API密钥 const currentWeatherApiTag = "你的API密钥"; const weekForecastApiTag = "你的API密钥"; const weatherData = { // 改为async方法,并行获取双API数据 async getWeatherInfo(city) { const currentWeatherUrl = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${currentWeatherApiTag}`; const weekWeatherUrl = `https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=imperial&appid=${weekForecastApiTag}`; try { // 并行请求两个API,提升效率 const [currentResponse, weekResponse] = await Promise.all([ fetch(currentWeatherUrl), fetch(weekWeatherUrl) ]); const currentData = await currentResponse.json(); const weekData = await weekResponse.json(); // 分别渲染当前天气和5天预报 this.displayCurrentWeather(currentData); this.displayWeekForecast(weekData); } catch (error) { console.error("获取天气数据失败:", error); // 可在此添加用户可见的错误提示 } }, // 拆分渲染逻辑:当前天气 displayCurrentWeather(data) { const { name } = data; const { icon, description } = data.weather[0]; const { temp, humidity } = data.main; const { speed } = data.wind; document.querySelector("#City").innerText = `Weather in ${name}`; document.querySelector(".weather-icon").src = `http://openweathermap.org/img/wn/${icon}.png`; document.querySelector("#CityWeatherDescription").innerText = description; document.querySelector("#Temperature").innerText = `${temp} °F`; document.querySelector(".humidity-weather-stat").innerText = `Humidity : ${humidity}%`; document.querySelector(".wind-speed-weather-stat").innerText = `Wind Speed : ${speed} m/hr`; }, // 新增:渲染5天预报逻辑 displayWeekForecast(data) { // 筛选每天中午12点的预报数据(OpenWeatherMap返回每3小时一条数据) const dailyForecasts = data.list.filter(item => item.dt_txt.includes("12:00:00")); const forecastContainer = document.querySelector("#WeekForecast"); // 需确保页面存在该容器 forecastContainer.innerHTML = ""; // 清空旧数据 dailyForecasts.forEach(forecast => { const date = new Date(forecast.dt * 1000).toLocaleDateString(); const { icon } = forecast.weather[0]; const { temp } = forecast.main; // 创建预报卡片元素 const forecastCard = document.createElement("div"); forecastCard.className = "forecast-card"; forecastCard.innerHTML = ` <p>${date}</p> <img src="http://openweathermap.org/img/wn/${icon}.png" alt="weather icon"> <p>${temp} °F</p> `; forecastContainer.appendChild(forecastCard); }); }, searchCurrentWeather() { const city = document.querySelector("#Search-Bubble").value.trim(); if (city) { this.getWeatherInfo(city); } }, }; // 事件监听 document.getElementById("SearchBtn").addEventListener("click", () => { weatherData.searchCurrentWeather(); }); document.getElementById("Search-Bubble").addEventListener("keyup", (event) => { if (event.key === "Enter") { weatherData.searchCurrentWeather(); } }); // 初始化加载Brooklyn的天气 weatherData.getWeatherInfo("Brooklyn");
关键修复点说明
- API请求优化:用
Promise.all并行请求两个API,比链式调用效率更高,若需顺序请求也可改为依次await。 this指向修正:事件回调用箭头函数,确保this指向weatherData;async方法内直接使用this即可。- 逻辑拆分:将当前天气和5天预报的渲染拆分为独立方法,避免代码冗余,提升可维护性。
- 错误处理:添加
try/catch捕获异步请求和数据解析时的错误,避免页面崩溃。 - 函数名统一:将调用与定义的函数名统一为
getWeatherInfo,解决函数未找到的问题。
链式Promise版本(若坚持使用链式调用)
const currentWeatherApiTag = "你的API密钥"; const weekForecastApiTag = "你的API密钥"; const weatherData = { getWeatherInfo(city) { const currentWeatherUrl = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${currentWeatherApiTag}`; const weekWeatherUrl = `https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=imperial&appid=${weekForecastApiTag}`; const self = this; // 提前保存this指向 fetch(currentWeatherUrl) .then(response => response.json()) .then(currentData => { self.displayCurrentWeather(currentData); return fetch(weekWeatherUrl); // 直接使用预定义的URL变量 }) .then(response => response.json()) .then(weekData => { self.displayWeekForecast(weekData); }) .catch(error => { console.error("获取天气数据失败:", error); }); }, // 以下displayCurrentWeather和displayWeekForecast方法与上面一致 displayCurrentWeather(data) { /* ... */ }, displayWeekForecast(data) { /* ... */ }, searchCurrentWeather() { /* ... */ }, }; // 事件监听和初始化逻辑与上面一致
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

