XMLHttpRequest(XHR)和 Fetch API 都是浏览器原生提供的网络请求工具,用于实现异步数据交互(如 AJAX),但两者在设计理念、功能特性和使用方式上存在显著差异。以下是它们的核心关系与详细区别分析:
🔗 一、核心关系
- 共同目标:
两者均用于在客户端发起 HTTP/S 请求,接收服务器响应,实现异步数据交换(AJAX)。 - 替代关系:
Fetch API 是 ES6 引入的现代化方案,旨在以更简洁、标准化的方式替代传统的 XMLHttpRequest,但并非基于 XHR 封装,而是全新的底层 HTTP 接口实现。
⚖️ 二、主要区别
1. 设计理念与语法
-
XMLHttpRequest(XHR):
- 基于事件回调:需手动监听
onreadystatechange事件,检查readyState和status处理响应,代码冗长。 - 示例代码:
const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.example.com/data', true); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { console.log(JSON.parse(xhr.responseText)); } }; xhr.send();
- 基于事件回调:需手动监听
-
Fetch API:
- 基于 Promise:支持链式调用(
.then())和async/await,代码更简洁。 - 示例代码:
fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error));
- 基于 Promise:支持链式调用(
2. 功能特性对比
| 特性 | XMLHttpRequest | Fetch API |
|---|---|---|
| 异步处理 | 回调函数,需手动管理状态 | Promise 链式调用,支持 async/await |
| 响应解析 | 需手动设置 responseType,如 xhr.responseText | 内置方法:response.json()、response.text() |
| 跨域请求 | 需设置 xhr.withCredentials = true | 需配置 { credentials: 'include' } |
| 错误处理 | 需检查 status,网络错误触发 onerror | 不自动处理 HTTP 错误(如 404),需手动检查 response.ok |
| 进度监控 | 支持 onprogress 事件(上传/下载) | 需通过 ReadableStream 手动实现 |
| 请求取消 | xhr.abort() | 通过 AbortController 实现 |
| 流式处理 | 不支持 | 支持 response.body 流式读取 |
3. 关键差异详解
-
错误处理机制:
- Fetch 仅在网络故障(如 DNS 解析失败)时触发
catch,HTTP 错误状态(404、500)仍返回resolve,需通过!response.ok手动拦截。 - XHR 在 HTTP 错误时可通过
status检查直接处理。
- Fetch 仅在网络故障(如 DNS 解析失败)时触发
-
默认行为:
- Fetch 默认不发送/接收 Cookies,需显式设置
credentials: 'include'。 - XHR 在同源请求中自动携带 Cookies。
- Fetch 默认不发送/接收 Cookies,需显式设置
-
取消请求:
- Fetch 依赖
AbortController:const controller = new AbortController(); fetch(url, { signal: controller.signal }); controller.abort(); // 取消请求 - XHR 直接调用
xhr.abort()。
- Fetch 依赖
🌐 三、兼容性与适用场景
-
兼容性:
- XHR:支持所有浏览器(包括 IE6+),适合旧项目或兼容性要求高的场景。
- Fetch:仅支持现代浏览器(Chrome 42+、Firefox 39+),不兼容 IE。可通过
whatwg-fetch等 polyfill 扩展支持。
-
选型建议:
场景 推荐方案 理由 现代浏览器项目 Fetch API 代码简洁,支持流式处理,符合现代开发范式 兼容旧浏览器(如 IE) XMLHttpRequest 无需 polyfill,稳定支持 需监控上传/下载进度 XMLHttpRequest 内置 onprogress事件,实现简单需频繁取消请求 Fetch + AbortController 标准化取消机制,更灵活
💎 总结
- XMLHttpRequest:成熟稳定,兼容性极佳,适合传统项目或需精细控制请求(如进度监控)的场景。
- Fetch API:设计现代、语法简洁,适合新项目开发,尤其在流式处理和 Promise 集成上优势明显,但需注意错误处理和兼容性限制。
实际开发中:优先选用 Fetch,并搭配 async/await 提升可读性;若需兼容旧浏览器或进度跟踪,降级为 XHR 是更稳妥的选择。

1186

被折叠的 条评论
为什么被折叠?



