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

fetch API返回404时try/catch未生效的React请求问题

问题现象

接口请求URL通过模板字符串直接拼接用户输入内容,当用户输入不合法内容触发fetch API返回404状态码时,预期try/catch逻辑可捕获该异常,在控制台打印错误信息,页面展示「Error」提示,但实际运行时代码未进入catch分支,组件仍按正常流程渲染。

复现代码
import './cssdirect/App.css';
import Daily from './components/daily';
import {useState, useEffect} from 'react'
import Loading from './Loading';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHeart } from '@fortawesome/free-solid-svg-icons'

function App() {
const [loading, setLoading] = useState(true)
const [city, setCity] = useState('Paris')
const [weatherData, setWeather] = useState([])
const [error, setError] = useState(false)

const getWeather = async() =>{
  setLoading(true)
  setError(false)
  try{
    const resp = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=imperial`)
    const pResp = await resp.json()
    setWeather(pResp)
    setLoading(false)
  }
  catch(err){
    console.log("ERRRRROOOORRRR")
    setError(true)
  }
}

const handleSubmit = (e) =>{
  e.preventDefault()
  console.log(city) 
  getWeather()
}    

useEffect(()=>{
  getWeather()
},[])

  if(loading==true){
    
    return <>
    <h1 className='title'>Monkey Wit Da Weather</h1>
    <Loading/>
   
  </>
  }
  else if(error===true){
    return<>
    <h1>Error</h1>
    </>
  }
  else{
    return<>
      <h1 className='title'>Monkey Wit Da Weather</h1>
     <Daily {...weatherData} setCity={setCity} city={city} getWeather={getWeather} handleSubmit={handleSubmit}/>
   
     
    </>
  }
}

export default App;
问题原因

fetch API 本身不会在HTTP响应状态码为4xx、5xx时自动抛出异常,只有网络中断、CORS跨域拦截、请求被浏览器阻止这类导致请求完全无法完成的场景,fetch才会返回rejected状态的Promise,被catch分支捕获。
当接口返回404状态码时,fetch实际上是正常返回了resolve状态的Response对象,仅对象上的ok属性为false、status属性值为404,因此代码不会进入catch分支,会继续执行后续的resp.json()逻辑,将接口返回的错误报文当成正常天气数据存入状态,最终组件走正常流程渲染。
另外原代码的catch分支没有重置loading状态,真的触发异常时页面会一直卡在加载态。

修复方案
  • 拿到fetch返回的响应对象后,先通过resp.ok属性判断响应状态是否正常,状态异常时手动抛出错误触发catch逻辑
  • catch分支中补充loading状态重置,避免页面永久停留在加载态

修复后的getWeather方法代码如下:

const getWeather = async() =>{
  setLoading(true)
  setError(false)
  try{
    const resp = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=imperial`)
    // 主动校验响应状态,非2xx状态时手动抛错
    if (!resp.ok) {
      throw new Error(`Request failed with status: ${resp.status}`)
    }
    const pResp = await resp.json()
    setWeather(pResp)
    setLoading(false)
  }
  catch(err){
    console.log("ERRRRROOOORRRR", err)
    setError(true)
    // 出错时重置加载状态
    setLoading(false)
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:57:38