Fetch API 与 XMLHttpRequest

Fetch API vs XMLHttpRequest

我知道 Fetch API 使用 Promises 并且它们都允许您向服务器发出 AJAX 请求。

我读到 Fetch API 有一些额外的功能,这些功能在 XMLHttpRequest 中不可用(在 Fetch API polyfill 中,因为它基于 XHR).

Fetch API 有哪些额外的功能?

有些事情您可以使用 fetch 而不是 XHR:

  • 您可以将缓存 API 与请求和响应对象一起使用;
  • 您可以执行 no-cors 请求,从未实现 CORS 的服务器获取响应。您不能直接从 JavaScript 访问响应主体,但可以将其与其他 API 一起使用(例如缓存 API);
  • 流式响应(使用 XHR,整个响应缓冲在内存中,使用 fetch,您将能够访问低级流)。这在所有浏览器中尚不可用,但很快就会可用。

有一些事情可以用 XHR 做,而用 fetch 还不能做,但它们迟早会可用(阅读此处的 "Future improvements" 段落:https://hacks.mozilla.org/2015/03/this-api-is-so-fetching/):

  • 中止请求(这现在在 Firefox 和 Edge 中有效,正如@sideshowbarker 在他的评论中解释的那样);
  • 报告进度。

本文https://jakearchibald.com/2015/thats-so-fetch/包含更详细的描述。

获取

  • 缺少使用文档的内置方法
  • 无法设置超时yet
  • 无法覆盖 content-type 响应 header
  • 如果 content-length 响应 header 存在 但未公开 ,body 的总长度在流式传输期间未知
  • 如果请求已经完成,将调用信号的中止处理程序甚至
  • 无上传进度(支持 ReadableStream 个实例作为请求主体 yet to come
  • doesn't support --allow-file-access-from-files(铬)

XHR

  • 没有办法 发送 cookie(除了使用 non-standard mozAnon flagAnonXMLHttpRequest 构造函数)
  • 不能 return FormData 个实例
  • 没有等同于 fetchno-cors 模式
  • 始终遵循重定向

上面的答案很好,提供了很好的见解,但我和这篇 google developers blog entry 的观点相同,主要区别(从实际角度来看)是 built-in 从 fetch

返回的承诺

不必像这样编写代码

function reqListener() {
    var data = JSON.parse(this.responseText);
}

function reqError(err) { ... }

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

我们可以清理一些东西,用 promises 和现代语法写一些更简洁、更易读的东西

fetch('./api/some.json')
    .then((response) => {
        response.json().then((data) => { 
            ... 
        });
    })
    .catch((err) => { ... });