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

使用Fetch API请求不存在资源时为何直接进入catch块?

问题:Thunderbird中Fetch API处理404错误异常的疑问

我首次在新版Thunderbird中使用Fetch API,运行如下代码:

let uri = whatever();
window.fetch(uri)
  .then((response) => {
    console.log(`got response with status ${response.status}`);
    if (!response.ok) {
      throw new Error(`thrown response status: ${response.status}`);
    }
    return response.text();
  })
  .then((xhtml) => doStuff(xhtml))
  .catch((err) => console.error(`fetching failed: ${err}`));

当请求存在的资源时,代码正常运行(doStuff()执行相应操作);但请求有效服务器上不存在的页面时,控制台输出:

fetching failed: TypeError: NetworkError when attempting to fetch resource.

此时会进入catch块,但并非抛出我在then块中定义的错误。请问这是什么原因?以及如何区分资源不存在与其他错误(如无法连接服务器、超时等)?


分析与解决方案

原因分析

标准Fetch API的逻辑是:只有真正的网络故障(比如连不上服务器、DNS解析失败、超时)才会直接reject promise;像404、500这类HTTP错误状态码,promise依然会resolve,让你在then块里自行判断处理。但新版Thunderbird对Fetch做了定制化修改,把4xx/5xx这类HTTP错误也归类为网络错误,直接触发了promise reject,导致你写的错误判断代码根本没机会执行。

区分不同错误的解决方法

要绕过这个环境限制,你可以改用async/await结合try/catch,同时自定义错误标识来区分不同场景:

let uri = whatever();
async function fetchResource() {
  try {
    const response = await window.fetch(uri);
    // 先确认响应对象有效
    if (!response) {
      throw new Error("网络连接异常");
    }
    console.log(`got response with status ${response.status}`);
    if (!response.ok) {
      // 给HTTP错误添加状态码属性,方便后续区分
      const httpError = new Error(`HTTP错误: ${response.status}`);
      httpError.statusCode = response.status;
      throw httpError;
    }
    const xhtml = await response.text();
    doStuff(xhtml);
  } catch (err) {
    if (err.statusCode) {
      // 处理HTTP状态码相关错误
      if (err.statusCode === 404) {
        console.error(`资源不存在: ${err.message}`);
      } else if (err.statusCode >= 500) {
        console.error(`服务器内部错误: ${err.message}`);
      } else {
        console.error(`HTTP请求错误: ${err.message}`);
      }
    } else if (err.message.includes("NetworkError")) {
      // 处理真正的网络故障(无法连接、超时等)
      console.error(`网络连接失败: ${err.message}`);
    } else {
      // 兜底处理其他未知错误
      console.error(`请求失败: ${err.message}`);
    }
  }
}

fetchResource();

另外,你也可以查阅Thunderbird的扩展开发文档,看看是否有配置项能让Fetch回归标准行为——也就是把HTTP错误状态码视为resolve而非reject,这样就能沿用你最初的then链式写法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:15:04