【问题标题】:Fetch API vs XMLHttpRequest获取 API 与 XMLHttpRequest
【发布时间】:2016-06-03 15:18:18
【问题描述】:

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

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

Fetch API 有哪些额外功能?

【问题讨论】:

  • 虽然我当时不记得了,但你可以用 XHR 做一两件事,而用 fetch 做不到。你说你读过 fetch 有额外的可能性,那些文章如果不说它们是什么就不是很好
  • 发现了 fetch 不能做的两件事,而 XHR 则可以......你不能在 fetch 中设置自己的请求超时值,也不能获取进度事件
  • Fetch 对于大多数类型的 XMLHttpRequest 来说只是一种简化的处理方式。如果您的用例符合 Fetch 的功能,请使用它。当您深入了解它时,XMLHttpRequest API 对于大多数人使用它的目的来说是丑陋的。 Fetch 旨在提供一种更简洁的做事方式,不需要包装在 XMLHttpRequest 周围的库来使其可口。
  • @jfriend00,这不对,fetch不是一种简化的方式,而是一种更底层的方式(确实,XHR现在是用Fetch来定义的:xhr.spec.whatwg.org/#the-send%28%29-method)。
  • @Marco - 你怎么能不说fetch(url).then(function(data) (...)); 不比使用XMLHttpRequest 做同样的事情更简单呢?它可能还有很多其他功能,但天哪,它确实更容易用于常见的事情。这是一个清理过的 API。

标签: javascript ajax xmlhttprequest fetch-api


【解决方案1】:

您可以使用 fetch 而不是 XHR 来做一些事情:

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

你可以用 XHR 做一些你不能用 fetch 做的事情,但它们迟早会可用(阅读此处的“未来改进”段落:https://hacks.mozilla.org/2015/03/this-api-is-so-fetching/) :

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

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

【讨论】:

【解决方案2】:

获取

  • 缺少使用文档的内置方法
  • 无法设置超时yet
  • 无法覆盖内容类型响应标头
  • 如果内容长度响应标头存在但未公开,则在流式传输期间正文的总长度是未知的
  • 如果请求已完成,将调用信号的中止处理程序甚至
  • 没有上传进度(支持 ReadableStream 实例作为请求正文是 yet to come

XHR

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

【讨论】:

  • fetch 也缺少进度。使用 XHR,您可以通过 progress 事件跟踪进度
  • “无法覆盖响应的内容类型标头”...这只是一个坏主意。 'content-type 指示要返回的内容,而 BACKEND 应该将其指示给前端。事实上,内容类型应该是类型的“唯一标题”,因为请求的内容就是应该返回的内容。如果您想要与特殊子域或其他东西不同的服务,那么您可以单独处理特定功能。你正试图强迫 99% 的人接受 1% 的规则。
  • @Knu 是的,现在我们更先进了,我们可以轻松地自动化 90% 的解决方案,并让异常案例路由到不同的功能。
  • @rzr 不完全是,你得到了Response#body
【解决方案3】:

上面的答案很好,提供了很好的见解,但我与google developers blog entry 分享的观点相同,主要区别(从实际角度来看)是从@987654322 返回的内置承诺的便利性@

不必编写这样的代码

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();

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

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

【讨论】:

  • @TheOpti 您可以在 IE 11 中填充基本的 fetch 支持。您也可以在许多项目中将 IE11 作为受支持的浏览器删除,因为在许多用户群中 IE 11 的使用率现在低于 1%。
  • 我讨厌 IE,但我也不建议放弃 IE 支持,尤其是当有 polyfill 时。数百万人仍在使用 IE 和其他旧浏览器。就在几天前,我看到一个客户在使用 IE 后不得不告诉他不要使用它。当然,如果你的项目无论如何都不支持 IE,那么 polyfill 也无济于事。
  • @PHPGuru 咕噜!这让我很生气。 Internet Explorer 上完全无法使用所有最新的 Web 技术。 我希望人们至少会切换到 Microsoft Edge!我希望 MS 会向 IE 发出一个“更新”,它会完全禁用浏览器(或在允许使用之前显示一个 nag 屏幕)并告诉人们切换到另一个浏览器。
  • 我认为这是微软的纯粹营销。如果他们将 IE 留在安装了 Edge 的计算机上,那么他们希望人们会认为 Edge 是一个不同的浏览器(事实并非如此),而 IE 的坏名声会随着 IE 而消失。唯一的区别是 Edge 比 IE 更新。但如果你不确定自己是否拥有最新版本的 Edge,那么你还不如使用 IE。
  • @PHPGuru 作为一个在需要 IE11 支持的团队中工作了几年的人,我可以 100% 告诉你,即使是基于 IE 代码的 Edge 也非常不同并且更好地工作与 IE11 相比,这是一场噩梦。更重要的是,基于 Chromium 的新 Edge,本质上只是对 Chrome 的重新打包,于 2020 年 1 月发布,比您写此评论早一年多。对我来说真的很奇怪,人们仍然重复 Edge 只是 IE 的 FUD
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
  • 1970-01-01
相关资源
最近更新 更多