ajax到fetch的發展與比較

引言

隨着前端技術的飛速發展,傳統的Ajax,指 XMLHttpRequest(XHR),正逐步被Fetch所取代。三年前,我們還在用JQuery的$.ajax方法請求數據,一晃眼,axios和fetch都已經開始分別搶佔“請求”這個前端高地。本文將會嘗試着闡述他們之間的區別,並給出自己的一些理解。

XHR

首先來看一下應用XHR發送請求的方法,可以看到,XMLHttpRequest 是一個設計粗糙的 API,不符合關注分離(Separation of Concerns)的原則,配置和調用方式非常混亂,而且基於事件的異步模型寫起來也沒有現代的 Promise,generator/yield,async/await 友好。

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
  console.log(xhr.response);
};

xhr.onerror = function() {
  console.log("Oops, error");
};

xhr.send();

JQuery ajax

無需多言,JQuery ajax是對原生XHR的封裝,除此以外還增添了對JSONP的支持。JQuery ajax經過多年的更新維護,使用起來非常方便,優點無需多言;如果要說缺點,那就是:

  • 本身是針對MVC的編程,不符合現在前端MVVM的浪潮
  • 基於原生的XHR開發,XHR本身的架構不清晰,已經有了fetch的替代方案
  • JQuery整個項目太大,單純使用ajax卻要引入整個JQuery非常的不合理(採取個性化打包的方案又不能享受CDN服務)

儘管JQuery對我們前端的開發工作曾有着(現在也仍然有着)深遠的影響,但是我們可以看到隨着VUE,REACT新一代框架的興起,以及ES規範的完善,更多API的更新,JQuery這種大而全的JS庫,未來的路會越走越窄。

$.ajax({
   type: 'POST',
   url: url,
   data: data,
   dataType: dataType,
   success: function () {},
   error: function () {}
});

Fetch

Fetch是AJAX的替代品,它的API是基於Promise設計的。
Fetch API 提供了一個 JavaScript接口,用於訪問和操縱HTTP管道的部分,例如請求和響應。它還提供了一個全局 fetch()方法,該方法提供了一種簡單,合理的方式來跨網絡異步獲取資源。
這種功能以前是使用 XMLHttpRequest實現的。Fetch提供了一個更好的替代方法,可以很容易地被其他技術使用,例如 Service Workers。

他的優點是:

  • 更加底層,提供的API豐富
  • 脫離了XHR,是ES規範裏新的實現方式
  • 基於標準 Promise 實現,支持 async/await
  • 語法簡潔,更加語義化,諸如:
fetch(url).then(response => response.json())
  .then(data => console.log(data))
  .catch(e => console.log("Oops, error", e))

使用async/await

try {
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}

相對的,Fetch也有一些缺點,首先就是兼容性的問題
在這裏插入圖片描述
可以看到,Fetch的兼容性並不好,但是通用引入一些polyfill,還是可以兼容IE8的

  • 由於 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham
  • 引入 Promise 的 polyfill: es6-promise
  • 引入 fetch 探測庫:fetch-detector
  • 引入 fetch 的 polyfill: fetch-ie8
  • 可選:如果你還使用了 jsonp,引入 fetch-jsonp
  • 可選:開啓 Babel 的 runtime 模式,使用 async/await

Fetch和Ajax區別

fetch規範與jQuery.ajax()主要有以下三點不同:

  1. 當接收到一個代表錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記爲 reject, 即使該 HTTP響應的狀態碼是 404 或 500。相反,它會將 Promise 狀態標記爲 resolve (但是會將 resolve 的返回值的 ok屬性設置爲 false ),僅當網絡故障時或請求被阻止時,纔會標記爲 reject。
  2. fetch() 不會接受跨域 cookies;你也不能使用fetch()建立起跨域會話。其他網站的Set-Cookie頭部字段將會被無視。
  3. fetch 不會發送 cookies。除非你使用了credentials的初始化選項,
    設置 fetch(url, {credentials: ‘include’})。
    (自2017年8月25日以後,默認的credentials政策變更爲same-origin。Firefox也在61.0b13版本中,對默認值進行修改)
發佈了5 篇原創文章 · 獲贊 5 · 訪問量 622
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章