你不須要jQuery(三):新AJAX方法fetch()

XMLHttpRequest來完成ajax有些老而過期了。javascript

fetch()能讓咱們完成相似 XMLHttpRequest (XHR) 提供的ajax功能。它們之間的主要區別是,Fetch API 使用了 Promises,它讓接口更簡單、簡潔,避免了回調的複雜性,省去了使用複雜的 XMLHttpRequest API。java

若是你以前未使用過 Promises,你應該先看看《JavaScript Promises 用法》這篇文章。web

基本Fetch用法

讓咱們先用一個例子來比較一下使用 XMLHttpRequest 和使用 fetch 之間的不一樣。咱們要請求一個URL,獲取JSON格式的返回結果。ajax

XMLHttpRequest

一個 XMLHttpRequest 請求須要兩個監聽器來捕捉 success 和 error 兩種情形,並且須要調用 open() 和 send() 方法。json

function reqListener() {  
  var data = JSON.parse(this.responseText);  
  console.log(data);  
}

function reqError(err) {  
  console.log('Fetch Error :-S', err);  
}

var oReq = new XMLHttpRequest();  
oReq.onload = reqListener;  
oReq.onerror = reqError;  
oReq.open('get', './api/some.json', true);  
oReq.send();

  

Fetch

咱們的 fetch 請求的代碼基本上是這樣的:api

fetch('./api/some.json')  
  .then(  
    function(response) {  
      if (response.status !== 200) {  
        console.log('Looks like there was a problem. Status Code: ' +  
          response.status);  
        return;  
      }

      // Examine the text in the response  
      response.json().then(function(data) {  
        console.log(data);  
      });  
    }  
  )  
  .catch(function(err) {  
    console.log('Fetch Error :-S', err);  
  });

  

咱們首先檢查請求響應的狀態是不是 200,而後才按照 JSON 對象分析響應數據。promise

fetch()請求獲取的內容是一個 Stream 對象。也就是說,當咱們調用 json() 方法時,返回的還是一個 Promise 對象,這是由於對 stream 的讀取也是異步的。服務器

返回數據對象的元數據(Metadata)

在上面的例子中,我看到了服務器響應對象Response的基本狀態,以及如何轉換成JSON。返回的相應對象Response裏還有不少的元數據信息,下面是一些:cookie

fetch('users.json').then(function(response) {  
    console.log(response.headers.get('Content-Type'));  
    console.log(response.headers.get('Date'));

    console.log(response.status);  
    console.log(response.statusText);  
    console.log(response.type);  
    console.log(response.url);  
});

  

響應的對象Response類型

當咱們執行一個fetch請求時,響應的數據的類型response.type能夠是「basic」, 「cors」 或 「opaque」。這些類型用來講明應該如何對待這些數據和數據的來源。app

當請求發起自同一個域時,響應的類型將會是「basic」,這時,對響應內容的使用將沒有任何限制。

若是請求來自另外某個域,並且響應的具備CORs頭信息,那麼,響應的類型將是「cors」。 「cors」 和 「basic」 類型的響應基本是同樣的,區別在於,「cors」類型的響應限制你只能看到的頭信息包括`Cache-Control`, `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, 和 `Pragma`。

「opaque」類型的響應說明請求來自另一個域,而且不具備 CORS 頭信息。一個opaque類型的響應將沒法被讀取,並且不能讀取到請求的狀態,沒法看到請求的成功與否。當前的 fetch() 實現沒法執行這樣的請求。緣由請參考這篇文章

你能夠給fetch請求指定一個模式,要求它只執行規定模式的請求。這個模式能夠分爲:

  • 「same-origin」 只有來自同域的請求才能成功,其它的均將被拒絕。
  • 「cors」 容許不一樣域的請求,但要求有正確的 CORs 頭信息。
  • 「cors-with-forced-preflight」 在執行真正的調用前先執行preflight check
  • 「no-cors」 目前這種模式是沒法執行的。

定義模式的方法是,使用一個參數對象當作fetch方法的第二個參數:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})  
  .then(function(response) {  
    return response.text();  
  })  
  .then(function(text) {  
    console.log('Request successful', text);  
  })  
  .catch(function(error) {  
    log('Request failed', error)  
  });

  

串聯 Promises

Promises最大的一個特徵是,你能夠串聯各類操做。對於fetch來講,咱們能夠在各個fetch操做裏共享一些邏輯操做。

在使用JSON API時,咱們須要檢查每次請求響應的狀態,而後解析成JSON對象。使用promise,咱們能夠簡單的將分析狀態和解析JSON的代碼放到一個單獨函數裏,而後當作promise返回,這樣就是代碼更條理了。

function status(response) {  
  if (response.status >= 200 && response.status < 300) {  
    return Promise.resolve(response)  
  } else {  
    return Promise.reject(new Error(response.statusText))  
  }  
}

function json(response) {  
  return response.json()  
}

fetch('users.json')  
  .then(status)  
  .then(json)  
  .then(function(data) {  
    console.log('Request succeeded with JSON response', data);  
  }).catch(function(error) {  
    console.log('Request failed', error);  
  });

  

咱們用 status 函數來檢查 response.status 並返回 Promise.resolve() 或 Promise.reject() 的結果,這個結果也是一個 Promise。咱們的fetch() 調用鏈條中,首先若是fetch()執行結果是 resolve,那麼,接着會調用 json() 方法,這個方法返回的也是一個 Promise,這樣咱們就獲得一個分析後的JSON對象。若是分析失敗,將會執行reject函數和catch語句。

你會發現,在fetch請求中,咱們能夠共享一些業務邏輯,使得代碼易於維護,可讀性、可測試性更高。

用fetch執行表單數據提交

在WEB應用中,提交表單是很是常見的操做,用fetch來提交表單數據也是很是簡潔。

fetch裏提供了 method 和 body 參數選項。

fetch(url, {  
    method: 'post',  
    headers: {  
      "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"  
    },  
    body: 'foo=bar&lorem=ipsum'  
  })
  .then(json)  
  .then(function (data) {  
    console.log('Request succeeded with JSON response', data);  
  })  
  .catch(function (error) {  
    console.log('Request failed', error);  
  });

  

在Fetch請求裏發送用戶身份憑證信息

若是你想在fetch請求裏附帶cookies之類的憑證信息,能夠將 credentials參數設置成 「include」 值。

fetch(url, {  
  credentials: 'include'  
})

  顯而易見,fetch API相比起傳統的 XMLHttpRequest (XHR) 要簡單的多,相比起jQuery裏提供ajax API也絲絕不遜色。

相關文章
相關標籤/搜索