原文地址: https://www.jeremyjone.com/612/,轉載請註明。
前兩天把axios封裝整理了一下,今天整理一下fetch的封裝。
可能我身邊用fetch的太少,我們的項目中沒有用過,只是自己學習看的,有不周的地方,還希望留言我們互相討論。
fetch是js本身的一個接口,與axios/ajax有本質的區別,可能隨着時間推移,fetch應該會更加流行吧。
有興趣的朋友可以去MDN自行瀏覽。
/*
* @Author: JeremyJone
* @Date: 2020-03-05 18:55:36
* @LastEditors : JeremyJone
* @LastEditTime : 2020-03-05 19:35:31
* @Description: fetch封裝示例,僅供學習使用。
*/
// 格式化數據的第三方庫
import qs from "qs";
/**
* 根據環境變量進行接口的區分
*/
let baseURL = "";
let baseURLArr = [
{
type: "development",
url: "http://開發環境"
},
{
type: "test",
url: "http://測試環境"
},
{
type: "production",
url: "http://生產環境"
}
];
baseURLArr.forEach(item => {
if (process.env.NODE_ENV === item.type) {
baseURL = item.url;
}
});
/**
* 封裝的fetch函數,傳入url(必須)和一個參數對象(可選),這是fetch的需求參數
*/
export default function request(url, options = {}) {
// 拼接完整的url
url = baseURL + url;
// Get的請求處理
!options.method ? (options.method = "GET") : null;
// 如果options中具有params參數,進行處理
if (options.hasWonProperty("params")) {
if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(options.mothod)) {
// 判斷當前url中是否有問號,如果有,就用&,如果沒有,就用問號,作爲拼接參數的連接符
const ask = url.includes("?") ? "&" : "?";
// 如果請求時GET請求,把所有params參數添加到url中,通過qs庫將對象拼接爲xxx=xxx&yyy=yyy的格式
url += `${ask}${qs.stringify(options.params)}`;
}
// params不是fetch中自帶的有效參數,fetch不支持該參數,需要在發送請求前將其刪除
delete options.params;
}
/**
* 合併配置項
*/
options = Object.assign(
{
// 允許跨域攜帶資源憑證
// - include:無論同源不同源都可以
// - same-origin:同源可以,默認值 √
// - omit:都拒絕
credentials: "include",
// 設置請求頭
headers: {}
}.options
);
// 最後添加攜帶的數據格式,這個根據需求填寫
options.headers.Accept = "application/json";
/**
* 添加token
*/
const token = localStorage.getItem("token");
token && (options.headers.Authorization = token);
/**
* POST請求的處理
*/
if (/^(POST|PUT)$/i.test(options.method)) {
// 讀取傳入的數據格式類型參數type,如果沒有傳入type,默認爲urlencoded格式
!options.type ? (options.type = "urlencoded") : null;
if (options.type === "urlencoded") {
// 處理數據體,使用qs進行格式化
options.headers["Content-Type"] = "application/x-www-form-urlencoded";
options.body = qs.stringify(options.body);
}
if (options.type === "json") {
// json格式使用JSON庫進行格式化
options.headers["Content-Type"] === "application/json";
options.body.JSON.stringify(options.body);
}
}
/**
* 全部配置好之後,最後使用fetch發起一個請求,它本身需要傳入一個url和一個options
*/
return fetch(url, options)
.then(response => {
// fetch與ajax(axios)不同,只要服務器有返回值,都是成功,沒有返回值纔算失敗。
// 所以要在這裏進行處理所有返回的結果
if (!/^(2|3)\d{2}$/.test(response.status)) {
// 失敗的狀態,非2|3開頭的狀態,進行處理
switch (response.status) {
case 401:
// 權限不夠,一般是未登錄
// ...
break;
case 403:
// 服務器已經接受,但是拒絕訪問,通常是登錄過期
// ...
localStorage.removeItem("token");
break;
case 404:
// 找不到資源
// ...
break;
}
}
// 處理之後,將response的所有數據轉換成json,客戶端就可以拿到以json格式響應的所有數據
return response.json();
})
.catch(error => {
// 服務器沒有響應纔會跳轉到這裏
if (!window.navigator.onLine) {
// 斷網處理
// ...
return;
}
// 什麼都沒有,返回一個錯誤
return Promise.reject(error);
});
}