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

weiqinl發表於2019-07-31

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

相關文章