前后端數據交互(四)——fetch 請求詳解


fetch 是 XMLHttpRequest 的升級版,使用js腳本發出網絡請求,但是與 XMLHttpRequest 不同的是,fetch 方式使用 Promise,相比 XMLHttpRequest 更加簡潔。所以我們告別XMLHttpRequest,引入 fetch 如何使用?

一、fetch介紹

fetch() 是一個全局方法,提供一種簡單,合理的方式跨網絡獲取資源。它的請求是基於 Promise 的,需要詳細學習 Promise ,請點擊《 Promise詳解 》。它是專門為了取代傳統的 xhr 而生的。

1.1、fetch使用語法

fetch(url,options).then((response)=>{ //處理http響應 },(error)=>{ //處理錯誤 })

url :是發送網絡請求的地址。

options:發送請求參數,

  • body - http請求參數
  • mode - 指定請求模式。默認值為cros:允許跨域;same-origin:只允許同源請求;no-cros:只限於get、post和head,並且只能使用有限的幾個簡單標頭。
  • cache - 用戶指定緩存。
  • method - 請求方法,默認GET
  • signal - 用於取消 fetch
  • headers - http請求頭設置
  • keepalive - 用於頁面卸載時,告訴瀏覽器在后台保持連接,繼續發送數據。
  • credentials - cookie設置,默認omit,忽略不帶cookie,same-origin同源請求帶cookie,inclue無論跨域還是同源都會帶cookie。

1.2、response 對象

fetch 請求成功后,響應 response 對象如圖:

前后端數據交互(四)——fetch 請求詳解

 

  • status - http狀態碼,范圍在100-599之間
  • statusText - 服務器返回狀態文字描述
  • ok - 返回布爾值,如果狀態碼2開頭的,則true,反之false
  • headers - 響應頭
  • body - 響應體。響應體內的數據,根據類型各自處理。
  • type - 返回請求類型。
  • redirected - 返回布爾值,表示是否發生過跳轉。

1.3、讀取內容方法

response 對象根據服務器返回的不同類型數據,提供了不同的讀取方法。分別有:

  1. response.text() -- 得到文本字符串
  2. response.json() - 得到 json 對象
  3. response.blob() - 得到二進制 blob 對象
  4. response.formData() - 得到 fromData 表單對象
  5. response.arrayBuffer() - 得到二進制 arrayBuffer 對象

上述 5 個方法,返回的都是 promise 對象,必須等到異步操作結束,才能得到服務器返回的完整數據。

1.4、response.clone()

stream 對象只能讀取一次,讀取完就沒了,這意味着,上邊的五種讀取方法,只能使用一個,否則會報錯。

因此 response 對象提供了 clone() 方法,創建 respons 對象副本,實現多次讀取。如下:將一張圖片,讀取兩次:

const response1 = await fetch('flowers.jpg');
const response2 = response1.clone();

const myBlob1 = await response1.blob();
const myBlob2 = await response2.blob();

image1.src = URL.createObjectURL(myBlob1);
image2.src = URL.createObjectURL(myBlob2);

 

1.5、response.body()

body 屬性返回一個 ReadableStream 對象,供用戶操作,可以用來分塊讀取內容,顯示下載的進度就是其中一種應用。

const response = await fetch('flower.jpg');
const reader = response.body.getReader();
while(true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  console.log(`Received ${value.length} bytes`)
}

 

response.body.getReader() 返回一個遍歷器,這個遍歷器 read() 方法每次都會返回一個對象,表示本次讀取的內容塊。

二、請求時 POST 和 GET 分別處理

請求方式不同,傳值方式也不同。xhr 會分別處理 get 和 post 數據傳輸,還有請求頭設置,同樣 fetch 也需要分別處理。

2.1、get 方式

只需要在url中加入傳輸數據,options中加入請求方式。如下面代碼所示:

<input type="text" id="user"><br>
<input type="password" id="pas"><br>
<button onclick="login()">提交</button>
<script>
 function login(){
  fetch(`http://localhost:80/fetch.html?user=${user.value}&pas=${pas.value}`,{
   method:'GET'
  }).then(response=>{
   console.log('響應',response)
  })
 }
</script>

 

2.2、post 方式

使用 post 發送請求時,需要設置請求頭、請求數據等。

將上個實例,改寫成 post 方式提交數據,代碼如下:

fetch(`http://localhost:80/ES6練習題/53fetch.html`,{
 method:'POST',
 headers:{
  'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
 },
 body:`user=${user.value}&pas=${pas.value}`
 }).then(response=>{
  console.log('響應',response)
})

 

如果是提交json數據時,需要把json轉換成字符串。如

body:JSON.stringify(json)

如果提交的是表單數據,使用 formData轉化下,如:

body:new FormData(form)

上傳文件,可以包含在整個表單里一起提交,如:

const input = document.querySelector('input[type="file"]');

const data = new FormData();
data.append('file', input.files[0]);
data.append('user', 'foo');

fetch('/avatars', {
  method: 'POST',
  body: data
});

 

上傳二進制數據,將 bolb 或 arrayBuffer 數據放到body屬性里,如:

let blob = await new Promise(resolve =>   
  canvasElem.toBlob(resolve,  'image/png')
);

let response = await fetch('/article/fetch/post/image', {
  method:  'POST',
  body: blob
});

 

三、fetch 常見坑

3.1、fetch兼容性

fetch原生支持率如圖:

前后端數據交互(四)——fetch 請求詳解

 

fetch 是相對較新的技術,IE瀏覽器不支持,還有其他低版本瀏覽器也不支持,因此如果使用fetch時,需要考慮瀏覽器兼容問題。

解決辦法:引入 polyfill 完美支持 IE8 以上。

  • 由於 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham
  • 引入 Promise 的 polyfill:es6-promise
  • 引入 fetch 探測庫:fetch-detector
  • 引入 fetch 的 polyfill: fetch-ie8
  • 可選:如果你還使用了 jsonp,引入 fetch-jsonp
  • 可選:開啟 Babel 的 runtime 模式,現在就使用 async/await

polyfill 的原理就是探測fetch是否支持,如果不支持則用 xhr 實現。支持 fetch 的瀏覽器,響應中文會亂碼,所以使用 fetch-detector 和 fetch-ie8 解決亂碼問題。

3.2、fetch默認不帶cookie

傳遞cookie時,必須在header參數內加上 credentials:'include',才會像 xhr 將當前cookie 帶有請求中。

3.3、異常處理

fetch 不同於 xhr ,xhr 自帶取消、錯誤等方法,所以服務器返回 4xx 或 5xx 時,是不會拋出錯誤的,需要手動處理,通過 response 中的 status 字段來判斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM