對ajax、axios、fetch的認識

keep789發表於2018-09-19

前端請求資料主要有XMLHttpRequest(XHR)、ajax、axios、fetch等方式。

原生xhr請求

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();

ajax請求

//post請求
$.ajax({
   type: 'POST',
   url: url路徑,
   data: data,
   dataType: dataType,
   success: function (data) {
        console.log(data)
    },
   error: function () {}
});

//get請求
$.ajax({
   type: 'GET',
   url: url路徑,
   data: data,
   dataType: dataType,
   success: function (data) {
        console.log(data)
    },
   error: function () {}
});

axios請求

axios({
    method: 'post',     //或者 method: 'get',
    url: '/user/12345',
    data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

fetch請求

fetch(url).then(function(response) {
  return response.json();
}).then(function(data) {
  console.log(data);
}).catch(function(e) {
  console.log("Oops, error");
});
使用 ES6 的 箭頭函式 後:

fetch(url).then(response => response.json())
  .then(data => console.log(data))
  .catch(e => console.log("Oops, error", e))

這種 Promise 的寫法還是有 Callback 的影子,而且 promise 使用 catch 方法來進行錯誤處理的方式有點奇怪。不用急,下面使用 async/await 來做最終優化,async/await 是非常新的 API,屬於 ES7,目前尚在 Stage 1(提議) 階段。使用 Babel 開啟 runtime 模式後可以把 async/await 無痛編譯成 ES5 程式碼。也可以直接使用 regenerator 來編譯到 ES5

try {
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}
// 注:這段程式碼如果想執行,外面需要包一個 async function
fetch('/users.json', {
    method: 'post', 
    mode: 'no-cors',
    data: {}
}).then(function() { /* handle response */ });

對上述方法的理解:

ajax是對原生XHR的封裝,除此以外還增添了對JSONP的支援。優點很多,缺點的話:

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

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

axios是在Vue2.0之後被尤雨溪推薦用替換JQuery ajax來使用的,Axios本質上也是對原生XHR的封裝,只不過它是Promise的實現版本,符合最新的ES規範。從其官網可看出其特性:

  • 從 node.js 建立 http 請求
  • 支援 Promise API
  • 客戶端支援防止CSRF
  • 提供了一些併發請求的介面(重要,方便了很多的操作)

注:支援防止CSRF就是讓你的每個請求都帶一個從cookie中拿到的key, 根據瀏覽器同源策略,假冒的網站是拿不到你cookie中得key的,這樣,後臺就可以輕鬆辨別出這個請求是否是使用者在假冒網站上的誤導輸入,從而採取正確的策略。

優點:

  • 提供了併發的封裝
  • 沒有下文會提到的fetch的各種問題
  • 體積也較小

看法:當之無愧是現在最應該選用的請求的方式。

fetch號稱是AJAX的替代品,它的好處:

  • 符合關注分離,沒有將輸入、輸出和用事件來跟蹤的狀態混雜在一個物件裡
  • 更好更方便的寫法

不管是Jquery還是Axios都已經幫我們把xhr封裝的足夠好,使用起來也足夠方便,我們還要花費大力氣去學習fetch主要是其主要優勢:

  • 更加底層,提供的API豐富(request, response)
  • 脫離了XHR,是ES規範裡新的實現方式

但是,正因為fetch是一個低層次的API,你可以把它考慮成原生的XHR,所以使用起來並不是那麼舒服,需要進行封裝。還有一些其他具體問題,如:

  • Fetch 請求預設是不帶 cookie 的,需要配置項,設定 fetch(url, {credentials: 'include'})
  • fetch只對網路請求報錯,對400,500都當做成功的請求,需要封裝去處理
  • fetch不支援abort,不支援超時控制,使用setTimeout及Promise.reject的實現的超時控制並不能阻止請求過程繼續在後臺執行,造成了流量的浪費
  • fetch沒有辦法原生監測請求的進度,而XHR可以

fetch在前端的應用上有一項xhr怎麼也比不上的能力:跨域的處理              fetch中可以設定mode為"no-cors"(不跨域)

看法:現在發展的還不是很完善,不大好用。

注:

1.大家也可以看看:https://segmentfault.com/a/1190000012836882

2.ajax的原理:相當於在使用者和伺服器之間加了—箇中間層,使使用者操作與伺服器響應非同步化。這樣把以前的一些伺服器負擔的工作轉嫁到客戶端,利於客戶端閒置的處理能力來處理,減輕伺服器和頻寬的負擔,從而達到節約ISP的空間及頻寬租用成本的目的。

3.xml和json,在ajax互動中,哪一種更易於開發和維護,js中怎麼序列化JSON字串? 

json相比xml可讀性和可擴張性好、編碼及解碼難度較低、在資料互動中頻寬佔用少,並且在當下是最流行的資料互動格式。

序列化JSON字串:eval() 或者 JSON.parse()  

4.總結一下目前接觸到的前後端互動的方法:

  • xhr
  • ajax
  • request--------nodejs
  • vue-resourse
  • axios
  • fetch
  • mui.ajax
  • wx.request
  • $http

 

相關文章