fetch API: 如何判断错误是否为网络错误

Fetch API: how to determine if an error is a network error

所以我有这样的代码:

async function getData() {
  const response = await fetch(/* ... */);
  const json = await response.json();
  return transform(json);
}

其中 transform 可以抛出一些它自己的错误。


我正在尝试从 fetch API.

中捕获网络错误
try {
  const data = await getData();

  // ...
  return // ...
} catch (e) {
  if (isNetworkError(e)) {
    return localStorage.getItem('...');
  }

  throw e;
}

我的问题是如何实现跨浏览器工作的 isNetworkError 注意:只有在网络离线时才 return 为真。

似乎 chrome 和 firefox 都会抛出一个 TypeError 但它们的消息各不相同。

如果第一个承诺被拒绝,这是一个网络错误。那是唯一一次。

The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.

来自 Mozilla 开发者页面: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

我没有一个完美的答案给你。解决您的确切问题最简单的方法是将 isNetworkError 实现为类型保护。也许 firefox/chrome 错误对象上有一些通用属性,可以让您专门检测到这些。

另一种方法是在离您更近的位置捕获错误 fetch(),然后将错误重新抛出为您可以轻松检测到的错误。

async function getData() {
  let response;

  try {
    response = await fetch(/* ... */);
  } catch (err) {
    throw new MyCustomNetworkError(err.message);
  }
  const json = await response.json();
  return transform(json);
}

作为 fetch 的客户端,您无法将网络错误与构建不正确请求引起的其他错误区分开来,因为两者都作为 TypeError 抛出。 (参见 https://developer.mozilla.org/en-US/docs/Web/API/fetch#exceptions)。

这是一个很大的缺陷,因为导致错误构建请求的应用程序缺陷可能不会被注意到,就像是偶然的网络错误一样被掩盖。