JS Fetch API詳解,XHR、Fetch和jQuery實現ajax的不同之處

Why Fetch

在開發過程中,我們向服務端發送請求,一般會使用三種方式, XMLHttpRequest(XHR),Fetch ,jQuery實現的AJAX。
其中, XMLHttpRequest(XHR)和Fetch是瀏覽器的原生API,jquery的ajax其實是封裝了XHR。
讓我們首先來比較一下這三者的使用示例。

XMLHttpRequest

var xhr;
if (window.XMLHttpRequest) {  // Mozilla, Safari...
   xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
   try {
     xhr = new ActiveXObject('Msxml2.XMLHTTP');
   } catch (e) {
     try {
       xhr = new ActiveXObject('Microsoft.XMLHTTP');
     } catch (e) {}
   }
}
if (xhr) {
   xhr.onreadystatechange = onReadyStateChange;
   xhr.open('POST', '/api', true);
   // 設置 Content-Type 爲 application/x-www-form-urlencoded
   // 以表單的形式傳遞數據
   xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
   xhr.send('username=admin&password=root');
}

// onreadystatechange 方法
function onReadyStateChange() {
  // 該函數會被調用四次
 console.log(xhr.readyState);
 if (xhr.readyState === 4) {
   // everything is good, the response is received
  if (xhr.status === 200) {
   console.log(xhr.responseText);
  } else {
   console.log(‘There was a problem with the request.’);
   }
 } else {
  // still not ready
  console.log(‘still not ready…’);
 }
}

從上邊的代碼可以看出,XMLHttpRequest 是一個非常粗糙的API,不符合關注分離(Separation of Concerns)的原則,配置和調用方式非常混亂,前端程序員們不僅要做各個瀏覽器的兼容性,還飽受回調地獄的折磨,這顯然不是一個好的選擇。

jQuery實現AJAX

$.ajax({
    method: 'POST',
    url: '/api',
    data: { username: 'admin', password: 'root' }
})
  .done(function(msg) {
      alert( 'Data Saved: ' + msg );
  });

jQuery作爲一個使用人數最多的庫,其AJAX很好的封裝了原生AJAX的代碼,在兼容性和易用性方面都做了很大的提高,而且jQuery還把jsonp裝在了AJAX裏面,這樣我們就可以開心的跨域了!!!!對比原生AJAX的實現,使用jQuery實現的AJAX就異常簡單了.
但是,筆鋒一轉,我們仍然逃脫不了一個問題,回調地獄。。。。

Fetch

fetch(...).then(fun2)
          .then(fun3) //各依賴有序執行
          .....
          .catch(fun)

從上邊的代碼可以看出,fetch用起來像jQuery一樣簡單,雖然還是有Callback的影子,但是看起來舒服多了


詳解Fetch API

兼容性

注意:由於Fetch API是基於Promise設計,舊瀏覽器不支持Promise,需要使用pollyfill es6-promise

  1. Fetch使用說明
fetch(url, options).then(function(response) { 
// handle HTTP response
}, function(error) {
 // handle network error
})

說明:
a. fetch api返回的是一個promise對象
b.Options:

  • method(String): HTTP請求方法,默認爲GET
  • body(String): HTTP的請求參數
  • headers(Object): HTTP的請求頭,默認爲{}
  • credentials(String): 默認爲omit,忽略的意思,也就是不帶cookie;還有兩個參數,same-origin,意思就是同源請求帶cookie;include,表示無論跨域還是同源請求都會帶cookie

c.第一個then函數裏面處理的是response的格式,這裏的response具體如下:


  • status(number): HTTP返回的狀態碼,範圍在100-599之間
  • statusText(String): 服務器返回的狀態文字描述,例如Unauthorized,上圖中返回的是Ok
  • ok(Boolean): 如果狀態碼是以2開頭的,則爲true
  • headers: HTTP請求返回頭
  • body: 返回體,這裏有處理返回體的一些方法
    • text(): 將返回體處理成字符串類型
    • json(): 返回結果和 JSON.parse(responseText)一樣
    • blob(): 返回一個Blob,Blob對象是一個不可更改的類文件的二進制數據
    • arrayBuffer()
    • formData()
  1. Fetch常見坑
  • 兼容性

如caniuse所示,IE瀏覽器完全不支持fetch,移動端的很多瀏覽器也不支持,所以,如果要在這些瀏覽器上使用Fetch,就必須使用fetch polyfill

  • cookie傳遞
    必須在header參數裏面加上credentials: 'include',纔會如xhr一樣將當前cookies帶到請求中去
  • fetch和xhr的不同
    fetch雖然底層,但是還是缺少一些常用xhr有的方法,比如能夠取消請求(abort)方法
    fetch在服務器返回4xx、5xx時是不會拋出錯誤的,這裏需要手動通過,通過response中的ok字段和status字段來判斷
  1. 實踐總結
    我們在實際應用中雖然會因爲它沒有interceptor等原因還需要再封裝一層,但fetch api仍然不失爲一個非常讚的API。。。。

4.參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章