You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用OpenWeather API时出现TypeError:无法解构data.main的'temp'属性问题求助

问题分析与解决方案

嘿,我来帮你拆解下你遇到的问题,主要有两个核心原因,咱们一个个说:

1. 地理定位的异步性导致初始请求无效

navigator.geolocation.getCurrentPosition是异步执行的——它不会立刻返回用户坐标,而是等浏览器获取到位置后才会调用successCallback。但你的setInterval在页面加载后100毫秒就开始调用fetchWeather了,这时候大概率successCallback还没执行,latUser[0]和lonUser[0]都是undefined。

这时候你请求API的URL会变成:
https://api.openweathermap.org/data/2.5/weather?lat=undefined&lon=undefined&units=metric&appid=xxx
OpenWeather API收到这种无效参数的请求,会返回错误响应,里面根本没有data.main字段,自然就会抛出解构失败的错误。

你说首次运行偶尔正常,只是刚好那次successCallback在100毫秒内完成了而已,这是概率问题,不是必然的。

2. 请求频率过高触发API限流

每100毫秒调用一次API,意味着每秒请求10次,这远远超过了OpenWeather免费版的请求限制(免费版通常是每分钟60次,也就是每秒1次)。很快API就会返回429 Too Many Requests的错误响应,这种响应的JSON里同样没有main字段,导致持续报错刷屏。


修复后的代码

我帮你调整了代码,解决了上面两个问题,还加了错误处理避免控制台爆炸:

/*Geolocation*/
let latUser;
let lonUser;
const errorCallback = (error) => {
  console.error("获取位置失败:", error);
};
const successCallback = (position) => {
  latUser = position.coords.latitude;
  lonUser = position.coords.longitude;
  // 拿到坐标后再开始定时请求天气,避免无效请求
  fetchWeatherRegularly();
};
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);

/*Weather*/
const weatherText = document.querySelector(".wtext");
const weatherCelsius = document.querySelector(".wcelsius");
const weatherHumidity = document.querySelector(".whumid");
const weatherIcon = document.querySelector(".weather-icon");

const weather = {
  apiKey: "*****",
  fetchWeather: function () {
    // 先检查坐标是否存在,避免无效请求
    if (!latUser || !lonUser) {
      console.warn("还未获取到用户坐标,跳过本次请求");
      return;
    }
    fetch(
      `https://api.openweathermap.org/data/2.5/weather?lat=${latUser}&lon=${lonUser}&units=metric&appid=${this.apiKey}`
    )
      .then((response) => {
        // 检查响应是否正常,处理限流或其他错误
        if (!response.ok) {
          throw new Error(`API请求失败:${response.status}`);
        }
        return response.json();
      })
      .then((data) => this.displayWeather(data))
      .catch((error) => {
        console.error("获取天气数据失败:", error);
        // 可以在这里给用户显示错误提示,比如"天气数据加载失败,请稍后重试"
      });
  },
  displayWeather: function (data) {
    const { temp, humidity } = data.main;
    const { description, icon } = data.weather[0];
    weatherText.innerText = description;
    weatherCelsius.innerText = `${temp}°C`;
    weatherHumidity.innerText = `Humidity: ${humidity}%`;
    weatherIcon.innerHTML = `<img src="icons/${icon}.png">`;
  },
};

// 改为5分钟请求一次(天气数据不会更新这么快),单位是毫秒
function fetchWeatherRegularly() {
  // 先立刻请求一次
  weather.fetchWeather();
  // 之后每5分钟请求一次
  setInterval(() => {
    weather.fetchWeather();
  }, 5 * 60 * 1000);
}

额外建议

  • 天气数据的更新频率很低,完全不需要每100毫秒请求一次,5-10分钟一次就足够了,既符合API限制,也能减少不必要的资源消耗。
  • 可以在页面上增加加载状态或错误提示,提升用户体验,比如位置获取失败时告诉用户,天气加载失败时显示友好提示。

内容的提问来源于stack exchange,提问作者veréb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:32:44