JS Fetch请求失败时的合理返回值方案探讨
优化Fetch请求的错误处理与返回类型
首先先修正你当前代码里的一个bug:第一个.then回调里没有返回res,导致第二个.then拿到的是undefined,根本没法调用res.json(),这会直接引发错误。先把这个问题解决掉:
export async function fetchFoo() { const data = await fetch(`http://localhost:9090/foo`, { method: "GET", redirect: "follow", }) .then((res) => { if (!res.ok) { throw new Error(res.statusText); // 用new Error更规范 } return res; // 必须返回res,后续才能调用json() }) .then(async (res) => await res.json()) .catch(() => undefined); return data; }
接下来针对你问的「失败时返回什么类型更合适」,推荐两种实用方案:
方案一:返回带状态标记的统一对象
这种方式能让调用方清晰区分请求成功/失败的状态,同时拿到对应的数据或错误信息,是前端最常用的模式之一。
修改后的函数:
export async function fetchFoo() { try { const res = await fetch(`http://localhost:9090/foo`, { method: "GET", redirect: "follow", }); if (!res.ok) { return { success: false, error: `请求失败:${res.status} ${res.statusText}`, data: null }; } const data = await res.json(); return { success: true, data, error: null }; } catch (err) { // 处理网络错误(比如断网、跨域等) return { success: false, error: `网络异常:${err.message}`, data: null }; } }
React组件中调用:
function FooComponent() { const [result, setResult] = useState(null); useEffect(() => { const loadData = async () => { const res = await fetchFoo(); if (res.success) { // 处理成功数据 console.log(res.data); } else { // 展示错误信息 alert(res.error); } setResult(res); }; loadData(); }, []); // 渲染逻辑... }
方案二:让调用方处理错误(不在fetch函数内catch)
如果希望组件能根据不同错误类型做更灵活的处理(比如区分404、500、网络错误),可以不在fetchFoo里捕获错误,而是让函数抛出错误,由调用方用try/catch处理。
修改后的函数:
export async function fetchFoo() { const res = await fetch(`http://localhost:9090/foo`, { method: "GET", redirect: "follow", }); if (!res.ok) { // 自定义错误对象,携带状态码等信息 const error = new Error(`请求失败:${res.statusText}`); error.statusCode = res.status; throw error; } return await res.json(); }
React组件中调用:
function FooComponent() { const [data, setData] = useState(null); const [error, setError] = useState(null); useEffect(() => { const loadData = async () => { try { const resData = await fetchFoo(); setData(resData); setError(null); } catch (err) { setError(err); setData(null); // 根据状态码做不同处理 if (err.statusCode === 404) { alert("资源不存在"); } else if (err.statusCode >= 500) { alert("服务器内部错误"); } else { alert(err.message); } } }; loadData(); }, []); // 渲染逻辑... }
两种方案各有优劣:方案一适合需要统一处理错误展示的场景,调用方逻辑更简洁;方案二适合需要精细化处理不同错误类型的场景,灵活性更高。你可以根据自己的业务需求选择。
内容的提问来源于stack exchange,提问作者ryno
相关产品推荐
相关产品推荐

