fetch詳解


window對象提供了一個fetch方法,用於實現基於promise的http請求。它取代了最早的XMLHttpRequest實現的ajax請求。

1. 基本內容

1. 基本語法

fetch方法返回一個promise對象。

const promise = fetch(url[, options]);

url--發起請求的路徑

options--可選設置。可以設置method, headers, body等,method默認是"GET"。

2. options配置對象

1. 如果不設置options, method默認是GET方法。

fetch(url)
// 相當於
fetch(url, {
   method: 'GET'
})

其傳參通過url傳參

fetch(url+ 'a=1&b=2')

2. 當請求方法為POST/PUT/DELETE等方法時,需要傳請求體body和對應的headers

const user = {name: "lyra"};
fetch(url, {
   method: 'POST',
   body: {// 請求體
      user: JSON.stringify(user)
   },
    headers: {// 請求頭
       Content-Type: "application/json;charset=utf-8"
    }
})

其中請求體body可以接受的參數類型有:

  • string  如:JSON格式, 其對應的請求頭為application/json; charset=utf-8
  • FormData對象   對應的Content-Type:form/multipart
  • ArrayBuffer/ArrayBufferView/Blob  二進制
  • URLSearchParams對象   對應的Content-Type:application/x-www-form-urlencoded

對於特殊的請求頭,如application/json,需要手動進行設置。

    headers: {// 請求頭
       Content-Type: "application/json;charset=utf-8"
    }

如果需要傳遞cookie的憑證,但是又存在跨域問題,則應該設置:

fetch(url, {
   // ⚠️ 此處的屬性不是位於headers內部
    credentials: "include" // 相當於xhr.withCredentials = true
})

如果使用JWT的用戶信息校驗機制,則需要設置請求頭

fetch(url, {
    headers: {
       // jwtToken是用戶登錄后,服務端返回的結果;一般存在localStorage中
       authorization: `Bearer ${jwtToken}`
    }
})

2. 響應對象

1. 獲取響應對象response

fetch請求的返回結果是promise內置的Response類的實例。該類提供了很多數據處理方法。

獲取response對象的方法有兩種:

/***考慮響應失敗,即promise的reject狀態**********
1. 網絡連接出現問題
2. 請求網址不存在
****************************/

//1. async..await
try {
   const response = await fetch(url, options)
}catch(e) {
   //當fetch的結果是reject
}

// 2. then
fetch(url, options).then(response =>{
   // response為響應對象; 主要服務器有響應404, 500也屬於resoloved狀態
}, () => {
    // reject狀態
})

2. response的屬性

  • response.ok   布爾值;狀態碼200-299時為true
  • reponse.status  http狀態碼
  • response.body  可讀流; 可以實時計算數據的下載量
// Step 1:啟動 fetch 並賦值給 reader
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');

const reader = response.body.getReader();

// Step 2:獲取總長度(總塊數)
const contentLength = +response.headers.get('Content-Length');

// Step 3:讀取數據
let receivedLength = 0; // 當前長度
let chunks = []; // 存放接收到的二進制塊的數組(包括 body)
while(true) {
  const {done, value} = await reader.read();

  if (done) {
    break;
  }

  chunks.push(value);
  receivedLength += value.length;

  console.log(`Received ${receivedLength} of ${contentLength}`)
}

// Step 4:將塊合並成單個 Uint8Array
let chunksAll = new Uint8Array(receivedLength); // (4.1)
let position = 0;
for(let chunk of chunks) {
  chunksAll.set(chunk, position); // (4.2)
  position += chunk.length;
}

// Step 5:解碼成字符串
let result = new TextDecoder("utf-8").decode(chunksAll);

// 我們完成啦!
let commits = JSON.parse(result);
alert(commits[0].author.login);
  • response.headers 響應頭

response.headers是一個類型Map類型的對象,可以通過get獲取內容

response.headers.get('Content-Type');
// 迭代所有的headers
for(let [key, value] of headers) {
   // key, value
}

3. response的方法

用於獲取對應類型的響應內容;其調用方法后的返回結果也是一個promise對象

⚠️下面解析請求體的方式只能使用一種;同時使用多種,只有第一個起作用。

  • response.json()  獲取json對象
  • response.text()  獲取文本
  • response.formData() 獲取FromData對象
  • response.blob()
  • response.arraybuffer() 二進制形式

 

數據處理的形式也有兩種:

// 1. async...await
try {
    const response = await fetch(url, options);
    const data = await response.json();
} catch (e) {
   // 
}


// 2. then
fetch(url, options)
.then(response => response.json()) .then(data => { //data }).catch(e= > { // })

3. 簡單封裝

封裝后實現,GET和POST等方式的請求體傳參形式相同。

// GET方法需要將對象轉為查詢參數
function obj2Str(obj) {
  let arr=[];
  for(let key in obj) {
    if (obj.hasOwnProperty(key)) {
      arr.push(`${key}=${obj[key]}`);
    }
  }
  return arr.join('&');
}

// 傳遞參數
const data = {
  a: 1,
  b: 2
}

async function requset(url, objData, method='GET', headers) {  
  /**1,2只需要使用一個**/
  const defaultOptions = {
    // 1. 如果后台使用session驗證用戶信息
    "credentials": "include",// 相當於xhr.withCredentials = true,
  }
  const options = {
    ...defaultOptions, 
    method,
    headers: {
      // 2. 如果后台使用JWT驗證用戶信息
      "Authorization": `Bearer ${jwtToken}`,
      ...headers
    }
  };
  if (method === 'GET') {
    // GET方法通過URL傳參
    url = `${url}?${obj2Str(objData)}`; 
  } else {
    options = {
      ...options,
      headers: {
        "Content-Type": "application/json; charset=utf-8",
        ...options.headers
      },
      body: JSON.stringify(data),  
    }
  }
  // 發起請求
  try {
    const response = await fetch(url, options);
    const data = await response.json();
    return data;
  } catch(e) {
    // 網絡問題或者URL不存在
  }
}

function get(url, obj, headers) {
  return requset(url, obj, 'GET', headers);
}

function post(url, obj, headers) {
  return requset(url, obj, 'POST', headers);
}

 


免責聲明!

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



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