浏览网页时,很多数据并不是随着HTML一次性返回,而是在页面加载之后由JavaScript继续向服务器请求。例如登录状态、商品列表、搜索结果、评论内容等,通常都需要通过网络请求动态获取。

在浏览器环境中,Fetch和XMLHttpRequest(通常简称XHR)都是常见的HTTP请求方式。两者都可以完成GET、POST等接口调用,但诞生背景和使用体验并不相同。

XHR是传统Ajax技术的核心,而Fetch则是现代浏览器提供的新一代网络请求接口。理解两者区别,可以帮助开发者更合理地处理前后端数据交互。

Fetch和XHR请求有什么区别?前端网络请求方式对比解析

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核心区别

比较项目XHRFetch
发布时间较早的传统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并不是简单的替代关系,而是代表了浏览器网络请求技术不同阶段的发展。理解两者的特点,比单纯判断哪个“更好”更重要。

参考资料

  1. MDN Fetch API文档

  2. MDN XMLHttpRequest文档

  3. Fetch标准规范