XMLHttpRequest 与 Fetch API哪个更适合 Ajax

权衡是否使用 XMLHttpRequest 与 Fetch 及其对 Ajax 的现代表现?我们比较两种选择的优缺点。

XMLHttpRequest1999 年作为 IE5.0 ActiveX 组件发布的第一个实现。在此之前,有一些方法可以在不刷新整页的情况下从服务器中提取数据,但它们通常依赖于笨拙的技术,例如<script>注入或第三方插件。微软XMLHttpRequest为他们的 Outlook 电子邮件客户端开发了一个基于浏览器的替代方案。

XMLHttpRequest直到 2006 年才成为 Web 标准,但它已在大多数浏览器中实现。它在 Gmail (2004) 和 Google Maps (2005) 中的采用导致了 Jesse James Garrett 的 2005 年文章AJAX: A New Approach to Web Applications。新术语明确了开发人员的重点。

AJAX到 Ajax

AJAX 是异步 JavaScript 和 XML 的助记符。“异步”肯定是,但是:

  1. JavaScript 是可能的,虽然 VBScript 和 Flash 是选项
  2. 有效负载不需要是 XML,尽管这在当时很流行。可以使用任何数据格式,如今,通常首选 JSON。

我们现在使用“Ajax”作为任何客户端进程的通用术语,它从服务器获取数据并动态更新 DOM 而无需刷新整个页面。Ajax 是大多数 Web 应用程序和单页应用程序 (SPA) 的核心技术。

极端 XMLHttpRequest

http://domain/service以下 JavaScript 代码显示了一个基本的HTTP GET 请求XMLHttpRequest(通常缩写为 XHR):

let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain/service');

// request state change event
xhr.onreadystatechange = function() {

  // request completed?
  if (xhr.readyState !== 4) return;

  if (xhr.status === 200) {
    // request successful - show response
    console.log(xhr.responseText);
  }
  else {
    // request error
    console.log('HTTP error', xhr.status, xhr.statusText);
  }
};

// start request
xhr.send();

XMLHttpRequest对象具有许多其他选项、​​事件和响应属性。例如,可以设置和检测以毫秒为单位的超时:

// set timeout
xhr.timeout = 3000; // 3 seconds
xhr.ontimeout = () => console.log('timeout', xhr.responseURL);

并且progress事件可以报告长时间运行的文件上传:

// upload progress
xhr.upload.onprogress = p => {
  console.log( Math.round((p.loaded / p.total) * 100) + '%') ;
}

选项的数量可能令人眼花缭乱,早期的实现XMLHttpRequest有一些跨浏览器的不一致。出于这个原因,大多数库和框架都提供了 Ajax 包装函数来处理复杂性,例如jQuery.ajax()方法:

// jQuery Ajax
$.ajax('http://domain/service')
  .done(data => console.log(data))
  .fail((xhr, status) => console.log('error:', status));

快进到Fetch

FetchXMLHttpRequest API是. 通用的HeadersRequestResponse接口提供了一致性,而 Promises 允许更轻松的链接和异步/等待而无需回调。上面的 XHR 示例可以转换为更简单的基于 Fetch 的代码,甚至可以解析返回的 JSON:

fetch(
    'http://domain/service',
    { method: 'GET' }
  )
  .then( response => response.json() )
  .then( json => console.log(json) )
  .catch( error => console.error('error:', error) );

Fetch 干净、优雅、易于理解,并且在PWA Service Workers中大量使用。为什么不使用它来代替古老的 XMLHttpRequest?

不幸的是,Web 开发从来没有那么明确。Fetch 还不能完全替代 Ajax 技术……

浏览器支持

Fetch API 得到了相当好的支持,但在所有版本的 Internet Explorer 中都会失败。使用早于 2017 年的 Chrome、Firefox 和 Safari 版本的用户也可能会遇到问题。这些用户可能只占您用户群的一小部分……或者可能是主要客户。在开始编码之前务必检查!

此外,与成熟的 XHR 对象相比,Fetch API 更新并接收更多的持续更改。这些更新不太可能破坏代码,但预计未来几年会进行一些维护工作。

默认无 Cookie

与 不同XMLHttpRequest的是,并非所有 Fetch 实现都会发送 cookie,因此您的应用程序的身份验证可能会失败。可以通过更改第二个参数中传递的启动选项来解决问题,例如

fetch(
    'http://domain/service',
    {
      method: 'GET',
      credentials: 'same-origin'
    }
  )

错误不被拒绝

令人惊讶的是,诸如404 Page Not Found或500 Internal Server Error之类的 HTTP 错误不会导致 Fetch Promise 拒绝;.catch()永远不会运行。它通常会在response.ok状态设置为 false 的情况下解决。

仅当请求无法完成时才会发生拒绝,例如网络故障。这会使错误捕获的实现更加复杂。

不支持超时

Fetch 不支持超时,只要浏览器选择,请求就会继续。需要进一步的代码来将 Fetch 包装在另一个 Promise 中,例如

// fetch with a timeout
function fetchTimeout(url, init, timeout = 3000) {
  return new Promise((resolve, reject) => {
    fetch(url, init)
      .then(resolve)
      .catch(reject);
    setTimeout(reject, timeout);
  }
}

… 或者Promise.race()当获取或超时首先完成时使用 to which 解决,例如

Promise.race([
  fetch('http://url', { method: 'GET' }),
  new Promise(resolve => setTimeout(resolve, 3000))
])
  .then(response => console.log(response))

中止Fetch

用函数结束 XHR 请求很容易xhr.abort(),如果有必要,可以用xhr.onabort函数检测这样的事件。

中止 Fetch 几年来是不可能的,但现在实现AbortController API的浏览器支持它。这会触发一个信号,该信号可以传递给 Fetch 启动对象:

const controller = new AbortController();

fetch(
  'http://domain/service',
  {
    method: 'GET'
    signal: controller.signal
  })
  .then( response => response.json() )
  .then( json => console.log(json) )
  .catch( error => console.error('Error:', error) );

可以通过调用来中止获取controller.abort();。Promise 拒绝,因此.catch()调用该函数。

没有进度

在撰写本文时,Fetch 不支持进度事件。因此,不可能报告文件上传或类似的大型表单提交的状态。

XMLHttpRequest 与 Fetch API?

最终,选择权在您手中……除非您的应用程序有需要上传进度条的 IE 客户端

对于更简单的 Ajax 调用,XMLHttpRequest它是较低级别的、更复杂的,并且您将需要包装函数。不幸的是,一旦您开始考虑超时、调用中止和错误捕获的复杂性,Fetch 也会如此。

您可以选择Fetch polyfillPromise polyfill,这样就可以在 IE 中编写 Fetch 代码。但是,XHR 被用作后备;并非每个选项都会按预期工作,例如无论设置如何都会发送 cookie。

Fetch是未来。但是,API 相对较新,它不提供所有 XHR 功能,而且有些选项很麻烦。在接下来的几年中谨慎使用它。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值