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

如何处理Fetch API网络故障,修复读取undefined的status错误?

解决Fetch API网络错误(如net::ERR_CONNECTION_REFUSED)的异常处理问题

我编写了以下工具函数处理网络请求,正常场景下运行正常,但遇到net::ERR_CONNECTION_REFUSED这类网络错误时,会抛出cannot read properties of undefined (reading 'status')错误,而非预期的“Failed to fetch”。尝试在checkStatus函数中添加if (!response.ok)的处理不仅无效,还会引发CORS错误。请问如何修正这个问题?

import configureStore from '../configureStore';
import { logout } from '../containers/App/actions';

const store = configureStore({});

/**
 * Parses the JSON returned by a network request
 *
 * @param  {object} response A response from a network request
 *
 * @return {object}          The parsed JSON from the request
 */
function parseJSON(response) {
  if (
    response.status === 204 ||
    response.status === 205 ||
    parseInt(response.headers.get('content-length')) === 0
  ) {
    return null;
  }
  return response.json();
}

/**
 * Checks if a network request came back fine, and throws an error if not
 *
 * @param  {object} response   A response from a network request
 *
 * @return {object|undefined} Returns either the response, or throws an error
 */
function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }

  const error = new Error(response.statusText);
  error.response = response;
  throw error;
}

/**
 * Requests a URL, returning a promise
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 *
 * @return {object}           The response data
 */
export default function request(url, options) {
  const headers = {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    'Access-Control-Request-Headers': 'Content-Type, Authorization'
  };
  const token = localStorage.getItem('token');
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }
  const newOptions = {
    ...options,
    mode: 'cors',
    headers
  };
  // FIXME
  // properly handle `net::ERR_CONNECTION_REFUSED`
  // currently, we return `cannot read properties of undefined (reading 'status')`
  return fetch(url, newOptions)
    .then(checkStatus)
    .then(parseJSON)
    .catch(err => {
      // check for 401 here and throw an action to clean the store and the logout.
      if (err.response.status === 401) {
        store.dispatch(logout);
      }
      throw err;
    });
}

问题根源

Fetch API的错误逻辑特殊:当发生net::ERR_CONNECTION_REFUSED这类网络层面错误时,fetch会直接将Promise置为reject状态,此时进入catch块的err对象并没有response属性——原代码直接访问err.response.status,自然会抛出“读取undefined的status属性”的错误。

另外,response.ok的判断无效是因为:网络错误根本不会走到checkStatus函数,只有服务器返回HTTP响应时,才会进入then链的checkStatus环节。

修正方案

修改catch块逻辑,先判断错误是否携带response属性:

  • 无response则判定为网络错误,抛出明确的“Failed to fetch”错误
  • 有response则处理HTTP状态码错误(如401登出)

同时推荐使用可选链操作符(?.)避免意外报错,修正后的request函数如下:

export default function request(url, options) {
  const headers = {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    'Access-Control-Request-Headers': 'Content-Type, Authorization'
  };
  const token = localStorage.getItem('token');
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }
  const newOptions = {
    ...options,
    mode: 'cors',
    headers
  };

  return fetch(url, newOptions)
    .then(checkStatus)
    .then(parseJSON)
    .catch(err => {
      // 处理网络错误:无response属性时抛出明确提示
      if (!err.response) {
        throw new Error('Failed to fetch');
        // 也可保留原始错误信息:throw err;
      }
      // 处理HTTP 401错误,用可选链避免报错
      if (err.response?.status === 401) {
        store.dispatch(logout);
      }
      throw err;
    });
}

额外说明

  • 网络错误(连接拒绝、DNS失败等)不会触发checkStatus,因为fetch不会返回任何HTTP响应
  • 可选链操作符err.response?.status可以替代显式的存在性判断,让代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:20:49