浏览网页时,很多数据并不是随着HTML一次性返回,而是在页面加载之后由JavaScript继续向服务器请求。例如登录状态、商品列表、搜索结果、评论内容等,通常都需要通过网络请求动态获取。
在浏览器环境中,Fetch和XMLHttpRequest(通常简称XHR)都是常见的HTTP请求方式。两者都可以完成GET、POST等接口调用,但诞生背景和使用体验并不相同。
XHR是传统Ajax技术的核心,而Fetch则是现代浏览器提供的新一代网络请求接口。理解两者区别,可以帮助开发者更合理地处理前后端数据交互。

XHR是什么以及为什么出现
XMLHttpRequest最早用于解决网页需要局部更新数据的问题。在它出现之前,网页通常需要重新加载整个页面才能获取服务器的新内容。
XHR让JavaScript可以在后台向服务器发送请求,并根据返回结果更新页面,因此推动了Ajax(Asynchronous JavaScript and XML)技术的发展。
虽然名称中包含XML,但实际开发中XHR并不限制返回格式。现在的网站更多使用JSON作为接口数据格式。
例如,一个页面点击按钮后获取用户信息:
const xhr = new XMLHttpRequest();
xhr.open("GET", "/api/user");
xhr.onload = function() {
console.log(xhr.responseText);
};
xhr.send();这种方式可以完成接口调用,但代码结构相对复杂,尤其是在多个请求、错误处理和异步流程管理方面。
Fetch是什么以及解决了什么问题
Fetch API是现代浏览器提供的一种网络请求接口,目标是提供更加简洁、基于Promise的HTTP请求方式。
相比XHR,Fetch采用了更符合现代JavaScript开发习惯的写法。
fetch("/api/user")
.then(response => response.json())
.then(data => {
console.log(data);
});开发者也可以结合async/await,使异步请求代码更接近同步阅读方式:
async function getUser() {
const response = await fetch("/api/user");
const data = await response.json();
console.log(data);
}因此,Fetch在现代前端项目中已经成为更常见的请求方式。
Fetch和XHR核心区别
| 比较项目 | XHR | Fetch |
|---|---|---|
| 发布时间 | 较早的传统Ajax技术 | 现代浏览器提供的新接口 |
| 异步处理方式 | 基于回调和事件 | 基于Promise |
| 代码结构 | 较复杂 | 更加简洁 |
| JSON处理 | 需要手动解析 | 提供response.json() |
| 请求取消 | 使用abort() | 通过AbortController |
| 流式读取 | 支持能力有限 | 原生支持ReadableStream |
| 上传下载进度 | 支持较完善 | 需要额外方案 |
异步处理方式有什么不同
两者最明显的区别之一,是处理异步结果的方法不同。
XHR主要依赖事件机制。例如请求完成后触发onload,请求失败后触发onerror。
xhr.onload = function() {
// 请求完成
};
xhr.onerror = function() {
// 请求失败
};当项目中存在多个接口依赖关系时,传统事件写法容易产生大量嵌套逻辑。
Fetch基于Promise设计,可以直接使用then、catch或者async/await组织代码。
fetch("/api/data")
.then(res => res.json())
.then(data => console.log(data))
.catch(error => console.error(error));对于现代前端框架和大型应用来说,Promise形式通常更容易维护。
错误处理方式有哪些差异
Fetch和XHR在错误处理方面存在一个容易忽略的区别。
XHR通常会在网络错误时触发error事件,而HTTP状态码错误,例如404或500,也需要开发者自行判断。
Fetch同样不会自动把404、500视为Promise reject。
fetch("/not-found")
.then(response => {
console.log(response.status);
});即使服务器返回404,只要服务器正常响应,Fetch仍然会进入then流程。
因此实际开发中通常需要检查response.ok:
fetch("/api/data")
.then(response => {
if (!response.ok) {
throw new Error("请求失败");
}
return response.json();
});这也是使用Fetch时需要特别注意的一点。
请求取消方式有什么区别
网页中有些请求可能不再需要继续执行,例如用户快速输入搜索关键词时,旧搜索请求可能已经没有意义。
XHR提供abort()方法:
xhr.abort();
Fetch则通过AbortController实现请求取消。
const controller = new AbortController();
fetch("/api/data", {
signal: controller.signal
});
controller.abort();AbortController不仅可以用于Fetch,也逐渐成为浏览器异步任务取消的一种通用方案。
Fetch为什么逐渐取代XHR
Fetch能够流行,主要原因并不是它提供了完全不同的HTTP能力,而是它更符合现代JavaScript的发展方向。
Promise让异步代码更容易组合。
async/await提高代码可读性。
API设计更加简洁。
支持现代浏览器流式数据处理。
更适合与现代前端框架结合。
目前React、Vue、Angular等现代开发环境中,经常可以看到基于Fetch或封装Fetch的请求方案。
不过,XHR并没有消失。一些旧项目、第三方库以及需要上传下载进度监控的场景,仍然可能继续使用XHR。
Fetch目前有哪些限制
虽然Fetch是现代开发中的主流选择,但它并不是所有场景都比XHR更方便。
其中比较明显的问题是上传和下载进度监听。
例如上传一个大型视频文件时,开发者通常希望显示“已经上传60%”这样的进度条。XHR提供了较成熟的progress事件,而Fetch原生支持方式相对有限。
另外,部分旧浏览器环境可能不支持完整Fetch功能,需要额外兼容处理。
因此,选择请求方式时仍然需要结合项目需求,而不是简单认为新技术一定适合所有情况。
如何选择Fetch和XHR
如果是新的网页项目,没有特殊兼容要求,大多数情况下优先考虑Fetch。
它的API设计更加符合现代JavaScript开发模式,也更容易和Promise、async/await结合。
如果项目已经大量使用XHR,或者需要精确控制上传下载进度,也没有必要为了追求新技术强行替换。
Fetch和XHR并不是简单的替代关系,而是代表了浏览器网络请求技术不同阶段的发展。理解两者的特点,比单纯判断哪个“更好”更重要。
poxiaoxi博客
精彩评论