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