異步請求xhr、ajax、axios與fetch的區別比較

  • 2019 年 10 月 3 日
  • 筆記

why: 為什麼會出現不同的方法呢?
what: 這些都是異步請求數據的方法。在不重新刷新頁面的情況下與服務器通信,交換數據,或更新頁面。
how:他們都有各自的特點。

1. XMLHttpRequest對象

現代瀏覽器,最開始與服務器交換數據,都是通過XMLHttpRequest對象。它可以使用JSON、XML、HTML和text文本等格式發送和接收數據。
它給我們帶來了很多好處

  1. 不重新加載頁面的情況下更新網頁
  2. 在頁面已加載後從服務器請求/接收數據
  3. 在後台向服務器發送數據。

但是,它也有一些缺點

  1. 使用起來也比較繁瑣,需要設置很多值。
  2. 早期的IE瀏覽器有自己的實現,這樣需要寫兼容代碼。
if (window.XMLHttpRequest) { // model browser    xhr = new XMLHttpRequest()  } else if (window.ActiveXObject) { // IE 6 and older    xhr = new ActiveXObject('Microsoft.XMLHTTP')  }  xhr.open('POST', url, true)  xhr.send(data)  xhr.onreadystatechange = function () {    try {      // TODO 處理響應      if (xhr.readyState === XMLHttpRequest.DONE) {        // XMLHttpRequest.DONE 對應值是 4        // Everything is good, the response was received.        if (xhr.status === 200) {          // Perfect!        } else {          // There was a problem with the request.          // For example, the response may hava a 404 (Not Found)          // or 500 (Internal Server Error) response code.        }      } else {        // Not ready yet      }    } catch (e) {      // 通信錯誤的事件中(例如服務器宕機)      alert('Caught Exception: ' + e.description)    }  }

2. jQuery ajax

為了更快捷的操作DOM,並且規避一些瀏覽器兼容問題,產生了jQuery。它裏面的AJAX請求也兼容了各瀏覽器,可以有簡單易用的方法$.get$.post。簡單點說,就是對XMLHttpRequest對象的封裝。

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

優點

  1. 對原生XHR的封裝,做了兼容處理,簡化了使用。
  2. 增加了對JSONP的支持,可以簡單處理部分跨域。

缺點

  1. 如果有多個請求,並且有依賴關係的話,容易形成回調地獄。
  2. 本身是針對MVC的編程,不符合現在前端MVVM的浪潮。
  3. ajax是jQuery中的一個方法。如果只是要使用ajax卻要引入整個jQuery非常的不合理。

3. axios

Axios是一個基於promiseHTTP庫,可以用在瀏覽器和 node.js 中。它本質也是對原生XMLHttpRequest的封裝,只不過它是Promise的實現版本,符合最新的ES規範。

axios({      method: 'post',      url: '/user/12345',      data: {        firstName: 'liu',        lastName: 'weiqin'      }    })    .then(res => console.log(res))    .catch(err => console.log(err))

Vue2.0之後,尤雨溪大大推薦大家使用axios來請求數據。
優點

  1. 從瀏覽器中創建XMLHttpRequests
  2. node.js 創建 http 請求
  3. 支持 Promise API
  4. 攔截請求和響應
  5. 轉換請求數據和響應數據
  6. 取消請求
  7. 自動轉換 JSON 數據
  8. 客戶端支持防禦 XSRF

缺點

  1. 只持現代代瀏覽器.

4. fetch

Fetch API提供了一個 JavaScript 接口,用於訪問和操作HTTP管道的部分,例如請求和響應。它還提供了一個全局fetch()方法,該方法提供了一種簡單,合理的方式來跨網絡異步獲取資源。
fetch是低層次的API,代替XHR,可以輕鬆處理各種格式,非文本化格式。可以很容易的被其他技術使用,例如Service Workers。但是想要很好的使用fetch,需要做一些封裝處理。

fetch('http://example.com/movies.json')    .then(function(response) {      return response.json();    })    .then(function(myJson) {      console.log(myJson);    });

優勢:跨域的處理
在配置中,添加mode: 'no-cors'就可以跨域了

fetch('/users.json', {      method: 'post',      mode: 'no-cors',      data: {}  }).then(function() { /* handle response */ });

fetch目前遇到的問題

  1. fetch只對網絡請求報錯,對400500都當做成功的請求,需要封裝去處理
  2. fetch默認不會帶cookie,需要添加配置項。
  3. fetch不支持abort,不支持超時控制,使用setTimeoutPromise.reject的實現超時控制並不能阻止請求過程繼續在後台運行,造成了流量的浪費。
  4. fetch沒有辦法原生監測請求的進度,而XHR可以。

請注意,fetch規範與jQuery.ajax()主要有兩種方式的不同,牢記:

-. 當接收到一個代表錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記為 reject, 即使該 HTTP 響應的狀態碼是 404500。相反,它會將 Promise 狀態標記為 resolve (但是會將 resolve的返回值的 ok 屬性設置為 false ),僅當網絡故障時或請求被阻止時,才會標記為 reject

-. 默認情況下,fetch 不會從服務端發送或接收任何 cookies, 如果站點依賴於用戶 session,則會導致未經認證的請求(要發送 cookies,必須設置 credentials 選項)。

參考

  1. MDN-使用Fetch
  2. 看雲-axios使用說明
  3. jQuery ajax()
  4. XMLHttpRequest