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

fetch请求超时未显示指定Sweetalert2,触发通用错误弹窗问题

请求超时后错误弹窗异常的修复方案

问题现象

  • 代码设置20秒请求超时,超时后通过controller.abort()取消请求,预期展示“服务器超时”的Sweetalert2弹窗,但实际触发了catch块中的通用错误弹窗
  • 控制台输出错误:DOMException: The user aborted a request

原代码

const envSoli = async () => {
  try {
    const controller = new AbortController();
    const signal = controller.signal;
    const timeId = setTimeout(() => {
      Swal.fire({
        //error timeout
        //custom function translate
        text: translate("text1"),
        icon: "info",
        buttonsStyling: false,
        confirmButtonText: translate("confirmbtn"),
        allowOutsideClick: false,
        allowEscapeKey: false,
        customClass: {
          confirmButton: "btn btn-info",
        },
        //refresh on ok click button
      }).then(function () {
        location.reload();
      });
       //controller.abort(), the idea is abort a request
       //after show the sweetalert
      controller.abort();
    }, 20 * 1000); // 20 sec
    let peticion = await fetch("data.php", {
      method: "POST",
      body: "ajax=1&do=check&lista=" + encodeURIComponent(leray[chenille]),
      headers: { "Content-type": "application/x-www-form-urlencoded" },
      cache: "no-cache",
      signal: signal,
    });
    clearTimeout(timeId);
    let oreen = await peticion.json();

    switch (oreen.enviando) {
      case -1:
        chenille++;
        document.getElementById("div1").append(oreen.cat + "<br />");
        updateProgress(chenille, leray.length);
        tvmit_wrongUp();
        break;

      case 1:
        chenille++;
        document.getElementById("div1").append(oreen.dog + "<br />");
        updateProgress(chenille, leray.length);
        tvmit_wrongUp();
        break;

      case 2:
        chenille++;
        document.getElementById("div2").append(oreen.sky + "<br />");
        nieva++;
        updateProgress(chenille, leray.length);
        tvmit_dieUp();
        break;

      case 3:
        chenille++;
        document.getElementById("div3").append(oreen.water + "<br />");
        tvmit_liveUp();
        updateProgress(chenille, leray.length);
        break;
    }

    OKTY(leray, chenille, aarsh, nieva);
    return true;
  } catch (error) {
    console.log(error);
    Swal.fire({
      text: translate("text2"),
      icon: "question",
      buttonsStyling: false,
      confirmButtonText: translate("confirmbtn"),
      allowOutsideClick: false,
      allowEscapeKey: false,
      customClass: {
        confirmButton: "btn btn-primary",
      },
      //refresh again on button click
    }).then(function () {
      location.reload();
    });
  }
};
envSoli();

问题根源

调用controller.abort()会让fetch请求抛出AbortError(属于DOMException的子类),这个错误会被try/catch的catch块捕获,导致通用错误弹窗被触发,覆盖了之前的超时提示弹窗。

修复步骤

  1. 区分错误类型:在catch块中判断错误是否为AbortError,如果是则跳过通用错误弹窗的逻辑——因为超时提示已经展示
  2. 调整超时逻辑顺序:先调用controller.abort()取消请求,再显示超时弹窗,逻辑更合理

修改后的代码

const envSoli = async () => {
  try {
    const controller = new AbortController();
    const signal = controller.signal;
    const timeId = setTimeout(() => {
      // 先取消请求,再展示超时提示
      controller.abort();
      Swal.fire({
        text: translate("text1"),
        icon: "info",
        buttonsStyling: false,
        confirmButtonText: translate("confirmbtn"),
        allowOutsideClick: false,
        allowEscapeKey: false,
        customClass: {
          confirmButton: "btn btn-info",
        },
      }).then(function () {
        location.reload();
      });
    }, 20 * 1000); // 20秒超时

    let peticion = await fetch("data.php", {
      method: "POST",
      body: "ajax=1&do=check&lista=" + encodeURIComponent(leray[chenille]),
      headers: { "Content-type": "application/x-www-form-urlencoded" },
      cache: "no-cache",
      signal: signal,
    });
    clearTimeout(timeId);
    let oreen = await peticion.json();

    switch (oreen.enviando) {
      case -1:
        chenille++;
        document.getElementById("div1").append(oreen.cat + "<br />");
        updateProgress(chenille, leray.length);
        tvmit_wrongUp();
        break;

      case 1:
        chenille++;
        document.getElementById("div1").append(oreen.dog + "<br />");
        updateProgress(chenille, leray.length);
        tvmit_wrongUp();
        break;

      case 2:
        chenille++;
        document.getElementById("div2").append(oreen.sky + "<br />");
        nieva++;
        updateProgress(chenille, leray.length);
        tvmit_dieUp();
        break;

      case 3:
        chenille++;
        document.getElementById("div3").append(oreen.water + "<br />");
        tvmit_liveUp();
        updateProgress(chenille, leray.length);
        break;
    }

    OKTY(leray, chenille, aarsh, nieva);
    return true;
  } catch (error) {
    console.log(error);
    // 仅当错误不是请求主动取消时,才展示通用错误弹窗
    if (error.name !== 'AbortError') {
      Swal.fire({
        text: translate("text2"),
        icon: "question",
        buttonsStyling: false,
        confirmButtonText: translate("confirmbtn"),
        allowOutsideClick: false,
        allowEscapeKey: false,
        customClass: {
          confirmButton: "btn btn-primary",
        },
      }).then(function () {
        location.reload();
      });
    }
  }
};
envSoli();

关键修改点

  • 超时回调中先执行controller.abort(),再弹出超时提示
  • catch块中增加error.name !== 'AbortError'的判断,过滤掉主动取消请求的错误,避免触发通用弹窗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:05:24