51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

XMLHttpRequest和Fetch API,您认为哪种最适合Ajax?

500.jpg

来台湾出差快一个星期了,相比大陆深圳,还是更喜欢内地多点,这边的天气实在不敢恭维,天天下雨,交通汽车尾气太重了,摩托车四处穿插.....休息时间还是呆在家里,写写东西,给大家分享点干货,今天来聊点数据ajax的基础知识。

2019年3月庆祝Ajax成立20周年。有点。XMLHttpRequest作为IE5.0 ActiveX组件于1999年交付的第一个实现(不要问)。

在此之前,曾经有一些方法可以在不刷新整个页面的情况下从服务器提取数据,但是它们通常依赖于笨拙的技术,例如<script>注入或第三方插件。Microsoft XMLHttpRequest为Outlook电子邮件客户端开发了一种基于浏览器的替代产品。

XMLHttpRequest直到2006年才成为Web标准,但大多数浏览器都实现了该标准。它在Gmail(2004)和Google Maps(2005)中的采用导致Jesse James Garrett在2005年发表的文章AJAX:一种新的Web应用程序方法。新术语明确了开发人员的重点。

AJAX to Ajax

AJAX是异步JavaScript和XML的助记符。绝对是"异步的",但是:

可以使用JavaScript,尽管可以选择VBScript和Flash

有效负载不必是XML,尽管在当时很流行。可以使用任何数据格式,今天,通常首选JSON。

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

极端XMLHttpRequest

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

let xhr = new XMLHttpRequest();xhr.open('GET', 'http://domain/service');// request state change eventxhr.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 requestxhr.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));

Fast Forward to Fetch

该提取API是一个现代化的替代品XMLHttpRequest。通用的Headers,Request和Response接口提供了一致性,而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 Worker中大量使用。为什么不使用它代替古老的XMLHttpRequest?

不幸的是,Web开发从未如此明确。Fetch尚未完全替代Ajax技术...

浏览器支持 {#browsersupport}

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

此外,与成熟的XHR对象相比,Fetch API较新,并且可以接收更多正在进行的更改。这些更新不太可能破坏代码,但是希望在未来几年中进行一些维护工作。

默认无Cookie {#cookielessbydefault}

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

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

错误不会被拒绝 {#errorsarenotrejected}

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

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

不支持超时 {#timeoutsarenotsupported}

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

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

...或也许Promise.race()首先获取或超时完成时使用哪个解析,例如:

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

Aborting a Fetch {#abortingafetch}

轻松终止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()调用该函数。

No Progress {#noprogress}

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

XMLHttpRequest与Fetch API?

最终,选择是您自己的...... 除非您的应用程序具有要求上载进度条的IE客户端。

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

您可以选择将Fetch polyfill与Promise polyfill结合使用,以便可以在IE中编写Fetch代码。但是,XHR被用作备用。并非每个选项都能按预期工作,例如,无论设置如何,都会发送Cookie。

获取是未来。但是,该API是相对较新的,它不提供所有XHR功能,并且某些选项比较繁琐。在接下来的几年中请谨慎使用。

总结

总而言之,XMLHttpRequest和Fetch API,对于我们Web前端工程师,都必须掌握,不同场景,不同项目,好自用之即可。

赞(0)
未经允许不得转载:工具盒子 » XMLHttpRequest和Fetch API,您认为哪种最适合Ajax?