fetch无原生timeout选项,{timeout: 5000}完全无效;必须用abortcontroller+promise.race实现真正中断:每次新建controller、显式传signal、超时调abort()、检查err.name==='aborterror'。

fetch 没有 timeout 选项,写 { timeout: 5000 } 完全无效——这不是兼容性问题,是规范根本不认这个字段。
fetch 超时必须用 AbortController + Promise.race
真正中断请求靠的是 controller.abort() 发信号,不是“等时间到了就不管它”。只靠 Promise.race 包一层超时 Promise,不传 signal,fetch 还在后台跑,可能后续触发 then 或 catch,造成状态错乱。
- 每次请求必须新建
AbortController,复用会导致多个请求互相 abort -
signal: controller.signal必须显式传进fetch()的 options,漏掉就等于没加超时 - 超时错误是
AbortError,检查要用err.name === 'AbortError',别只看err.message是否含 “timeout” - 示例中
setTimeout(() => controller.abort(), 8000)后,记得在then/catch里调用clearTimeout,否则可能重复报错
表单提交场景下 preventDefault 容易漏
原生 <form></form> 提交无法设超时,所谓“表单超时”本质是拦截后改用 fetch。漏掉 event.preventDefault(),页面会跳转或刷新,fetch 请求可能被中断,且用户看不到任何反馈。
- 必须在
submit事件监听里第一时间调用e.preventDefault() - 用
new FormData(form)构造请求体,别手动拼URLSearchParams(对文件无效) - 若用户中途关闭标签页,
beforeunload可补一次controller.abort(),但不能await任何异步操作 - 连续快速点击提交按钮时,前一个
controller未清理,新请求可能被旧 abort 误杀——建议每次提交前先controller.abort()(如果存在)
XMLHttpRequest 的 timeout 属性要按顺序设置
老项目或需兼容 IE 时,XMLHttpRequest 是唯一选择,但它对 timeout 设置位置极其敏感:必须在 open() 之后、send() 之前赋值,且必须绑定 ontimeout 事件,否则静默失效。
-
xhr.timeout = 5000写在xhr.open()前 → 被忽略 -
xhr.timeout = 5000写在xhr.onload里 → 完全无意义 - 超时仅覆盖网络传输阶段(DNS、TCP、发送、接收),不包括 JS 解析或 DOM 构建耗时
-
xhr.responseXML在多数浏览器中不可靠,建议用xhr.responseType = 'text'+DOMParser手动解析
真正难的不是写对那一行 controller.abort(),而是所有请求路径(表单、按钮点击、自动轮询)都得统一走同一套 abort 生命周期管理;稍一疏忽,就出现“超时提示弹了,但接口还在执行”的竞态问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











