Ajax 之战:XMLHttpRequest与Fetch API比较


Ajax 是大多数 Web 应用程序背后的核心技术。它允许页面向 Web 服务发出进一步的请求,因此无需页面刷新往返服务器即可呈现数据。
Ajax一词不是一种技术。相反,它指的是可以从客户端脚本加载服务器数据的技术。多年来已经引入了几种选择。仍然有两种主要方法,大多数 JavaScript 框架将使用一种或两种方法。

XMLHttpRequest
XMLHttpRequest1999 年首次作为非标准 Internet Explorer 5.0 ActiveX 组件出现。微软开发它是为了支持他们基于浏览器的 Outlook 版本。XML 是当时最流行(或被炒作)的数据格式,但XMLHttpRequest支持文本和尚未发明的 JSON。
XMLHttpRequest受到所有主流浏览器的支持,并于 2006 年成为官方 Web 标准。

const xhr = new XMLHttpRequest();
xhr.open("GET", "/service");

// state change event
xhr.onreadystatechange = () => {
  // is request complete?
  if (xhr.readyState !== 4) return;

  if (xhr.status === 200) {
    // request successful
    console.log(JSON.parse(xhr.responseText));
  } else {
    // request not successful
    console.log("HTTP error", xhr.status, xhr.statusText);
  }
};

// start request
xhr.send();

在请求的整个生命周期中,onreadystatechange回调函数会运行数次。XMLHttpRequest对象的readyState属性返回当前状态。

  • 0 (uninitialized) - 请求未被初始化
  • 1 (加载中) - 服务器连接建立
  • 2 (加载中) - 收到请求
  • 3 (交互式) - 处理请求
  • 4 (complete) - 请求完成,响应已准备好

在达到状态4之前,函数几乎无法做什么事情。

Fetch
Fetch是一个现代的基于Promise的Ajax请求API,首次出现在2015年,并被大多数浏览器所支持。它不是建立在XMLHttpRequest的基础上,并以更简洁的语法提供更好的一致性。下面的Promise链与上面的XMLHttpRequest例子功能相同。

fetch("/service", { method: "GET" })
  .then((res) => res.json())
  .then((json) => console.log(json))
  .catch((err) => console.error("error:", err));

或者使用 async / await::

try {
  const res = await fetch("/service", { method: "GET" }),
    json = await res.json();

  console.log(json);
} catch (err) {
  console.error("error:", err);
}


第一轮:Fetch获胜
除了更干净、更简洁的语法外,FetchAPI 还提供了一些优于老化的XMLHttpRequest:

  • 标头、请求和响应对象
  • 缓存控制
  • CORS 控制
  • 凭证控制
  • 重定向控制
  • 数据流
  • 服务器端支持

第 2 轮:XMLHttpRequest获胜
XMLHttpRequest但仍有一些技巧可以超越Fetch():

  • 进度支持
  • 超时支持
  • 中止支持
  • 更明显的故障检测
  • 浏览器支持