前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库fetch 与 XMLHttpRequest 区别
浏览浏览器请求与通信 API

浏览器中 fetch 与 XMLHttpRequest 的核心差异是什么,选型时怎么权衡?

fetch 是基于 Promise 的现代请求 API,XMLHttpRequest 基于事件回调;两者在错误语义、上传进度、取消机制上有实质差异,选型取决于具体需求而非新旧。

前端进阶之旅 · 一题精讲更新于 2026.09.05
浏览器#请求与通信 API#异步编程#HTTP
先看核心答案
理解线索

四差异一权衡的记忆线索

  1. Promise 与回调fetch 返回 Promise 可 await,XHR 走事件回调
  2. 错误语义不同fetch 对 4xx/5xx 不 reject,要看 response.ok
  3. 进度与取消上传进度只有 XHR 有;取消机制两者不同

需要上传进度或兼容极老环境时才考虑 XHR,其余场景优先 fetch。

核心回答

先记住这个答案

核心差异有四点:第一,fetch 返回 Promise,可配合 async/await 组织链式逻辑,XHR 依赖 onload、onerror 等事件回调。第二,fetch 收到 HTTP 404 或 500 时 Promise 依然 resolve,只有网络层失败才 reject,必须检查 response.ok;XHR 可通过 status 在回调中统一判断。第三,XHR 的 upload 对象支持上传进度事件,原生 fetch 无法监听上传进度。第四,fetch 用 AbortController 取消,XHR 用自身的 abort() 方法。选型上:需要上传进度或兼容极老环境用 XHR,其余场景优先 fetch 并自行封装错误检查与超时。

  • fetch 只在网络失败时 reject,HTTP 错误照常 resolve
  • XHR 支持上传进度,原生 fetch 做不到
  • fetch 用 AbortController 取消,XHR 用 abort()
  • 无特殊需求优先 fetch,但需封装 ok 检查

四个实质差异的机制来源

fetch 的设计把网络层与 HTTP 层分开:Promise 在收到响应头那一刻就 resolve,哪怕状态码是 500,因为传输本身成功了;只有 DNS 失败、连接中断、CORS 阻断这类网络层问题才 reject。XHR 则把一切都交给事件,onload 后由开发者读 status 判断,语义上反而更直白。

上传进度差异源于 API 结构:XHR 把上传通道暴露为 xhr.upload 对象并派发 progress 事件,而 fetch 的 Response 流只覆盖下载方向;流式请求体上传在 Chrome 105+ 才出现且需 duplex: 'half',仍无进度事件。取消方面,fetch 把取消信号外置为 AbortController,可复用到多个请求;XHR 的 abort() 是实例方法,终止后状态会被重置为未发送(readyState 0),同一对象可再次 open() 复用。

大文件上传与接口请求共存的选型

一个后台系统有两类请求:普通 JSON 接口,以及最大 2GB 的视频素材上传,产品要求上传时显示百分比进度条并允许中途取消。决策是:JSON 接口统一走 fetch,封装检查 response.ok、非 ok 抛出自定义错误;视频上传走 XHR,把 xhr.upload.onprogress 的 loaded/total 转成进度条,取消按钮调用 xhr.abort()。

这样处理的原因是硬约束驱动而非偏好:fetch 原生拿不到上传进度,若强行用 fetch 只能等结束后一次性反馈,2GB 文件下用户体验不可接受;而 JSON 接口用 XHR 则要手写回调包装,错误分支分散。结果是一套双轨封装,进度准确到分块,取消两种机制各自落地。

容易失效的假设与应对

最常见的失效假设是 fetch 的 catch 能捕获后端错误:实际上 404、500 都会进入 then,漏掉 ok 检查会把错误响应当成功数据解析,下游 response.json() 再抛解析错误,定位被严重误导。另一个边界是 fetch 没有 timeout 参数,慢请求会无限挂起,必须用 AbortController 加计时器或 AbortSignal.timeout() 自行实现。

对应处理都有代价:封装统一的 fetch 拦截器检查 ok 并抛出带 status 的错误,是所有调用方都要遵守的约定;XHR 的 timeout 属性虽内置,但只在整体超时维度工作;同步 XHR 已被废弃,不应再使用。取消请求时还要注意区分 AbortError 与真实网络错误,否则会把用户主动取消误报为故障告警。

回答前,多想一步

容易答错的地方

fetch 状态码 500 会进 catch
错误。fetch 只在网络层失败时 reject,500 会正常 resolve。必须在 then 中检查 response.ok 或 status,否则错误响应会被当作成功结果继续处理。
fetch 全面优于 XHR,可以彻底替代
不准确。原生 fetch 不支持上传进度,没有内置 timeout,旧环境兼容性也不如 XHR。在需要上传进度条的场景,XHR 仍是更简单直接的方案。
试着用自己的话回答

面试官还会怎么问?

fetch 如何正确取消一个请求?

创建 AbortController,把 controller.signal 传给 fetch,调用 controller.abort() 后 Promise 以 AbortError reject,浏览器同时关闭底层连接。需在 catch 中用 error.name === 'AbortError' 区分主动取消与网络失败。

为什么 XHR 能监听上传进度而 fetch 不能?

XHR 把上传通道暴露为 xhr.upload 对象并派发 progress 事件,而 fetch 的流能力主要覆盖响应下载方向。流式请求体上传需 Chrome 105+ 且设置 duplex: 'half',但依然不提供进度回调。

封装 fetch 时最应统一处理什么?

至少三件事:检查 response.ok 并抛出带 status 的错误、用 AbortSignal.timeout() 提供超时、集中处理 JSON 解析失败。否则每个调用方各自处理,容易漏掉 HTTP 错误分支导致隐性 bug。

从一道题,走向一组知识

把知识连起来

请求与通信 API

为什么 fetch 收到 HTTP 404 或 500 响应时 Promise 不会 reject,应该怎么处理?

本题指出 fetch 对 HTTP 错误不 reject,该文展开原因与标准处理写法

请求与通信 API

为什么原生 fetch 无法监听文件上传进度,有哪些替代方案?

上传进度是选 XHR 的决定性理由,该文详解限制与替代方案

参考资料

  • Fetch API

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 四个实质差异的机制来源
  3. 大文件上传与接口请求共存的选型
  4. 容易失效的假设与应对
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑