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

如何等待fetchData()完成后再执行依赖其数据的fetchForecastData()?

解决顺序调用fetchData和fetchForecastData的问题

你的核心问题是两个异步函数执行顺序混乱,且依赖的lat/lon状态更新是异步的,导致fetchForecastData经常拿到初始空值发起无效请求,重启时这个问题更明显。下面给你两种靠谱的解决方案:

方案一:直接传递参数顺序执行(推荐,避免状态依赖)

修改fetchData让它返回获取到的经纬度,然后在useEffect里按顺序执行,直接把经纬度传给fetchForecastData,绕开React状态更新的异步延迟问题:

function App() {
  const [location, setLocation] = useState('');
  const [currentWeather, setCurrentWeather] = useState([]);
  const [weatherForecast, setWeatherForecast] = useState([]);
  const [lat, setLat] = useState('');
  const [lon, setLon] = useState('');

  const addSearchCity = (search) => {
    setLocation(search);
  };

  // 修改fetchData,返回经纬度
  const fetchData = async () => {
    const res = await axios(
      `https://api.openweathermap.org/data/2.5/weather?q=london&appid={API}&units=metric`,
    );
    setCurrentWeather(res.data);
    const { lat, lon } = res.data.coord;
    setLat(lat);
    setLon(lon);
    return { lat, lon }; // 返回经纬度
  };

  // 修改fetchForecastData,支持接收参数
  const fetchForecastData = async (lat, lon) => {
    const result = await axios(
      `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&appid={API}&units=metric`,
    );
    setWeatherForecast(result);
  };

  useEffect(() => {
    // 内部封装async函数,保证顺序执行
    const fetchAllData = async () => {
      const coords = await fetchData();
      // 拿到经纬度后再调用预报接口
      await fetchForecastData(coords.lat, coords.lon);
    };
    fetchAllData();
  }, []);
}

方案二:监听经纬度状态变化触发请求

利用React的状态依赖特性,当lat和lon更新为有效值时,自动调用fetchForecastData:

function App() {
  const [location, setLocation] = useState('');
  const [currentWeather, setCurrentWeather] = useState([]);
  const [weatherForecast, setWeatherForecast] = useState([]);
  // 初始设为null,方便判断是否有有效值
  const [lat, setLat] = useState(null);
  const [lon, setLon] = useState(null);

  const addSearchCity = (search) => {
    setLocation(search);
  };

  const fetchData = async () => {
    const res = await axios(
      `https://api.openweathermap.org/data/2.5/weather?q=london&appid={API}&units=metric`,
    );
    setCurrentWeather(res.data);
    setLat(res.data.coord.lat);
    setLon(res.data.coord.lon);
  };

  const fetchForecastData = async () => {
    // 先判断经纬度是否有效,避免无效请求
    if (!lat || !lon) return;
    const result = await axios(
      `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&appid={API}&units=metric`,
    );
    setWeatherForecast(result);
  };

  // 初始加载只调用当前天气接口
  useEffect(() => {
    fetchData();
  }, []);

  // 监听lat和lon变化,有值时调用预报接口
  useEffect(() => {
    fetchForecastData();
  }, [lat, lon]);
}

原代码重启异常的原因

原useEffect里同时调用两个异步函数,fetchForecastData会先执行,此时lat和lon还是初始空字符串,发起的请求参数无效导致接口报错。重启时组件重新初始化,这个问题会重复出现。上面两种方案都能解决:

  • 方案一通过await强制顺序,直接传递参数,完全不依赖状态更新时机;
  • 方案二通过状态监听+有效值判断,确保只有拿到有效经纬度才发起请求。

内容的提问来源于stack exchange,提问作者Mliki Mliki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:15:43