axios的二次封裝和api介面規範
阿新 • • 發佈:2020-12-01
fetch是瀏覽器內建的類,進行資料請求,天生就是基於promise進行管理的
axios是基於ajax和promise進行封裝的庫
下面是axios封裝基本需求
// 二次封裝axios import axios from 'axios'; import { config } from 'process'; import qs from qs; // 根據環境變數區分介面的預設地址 switch(process.env.NODE_ENV){ case "production": //生產環境 axios.defaults.baseURL = "http://api.yanggengzhen.com";break; case "test": //測試環境 axios.defaults.baseURL = "http://192.168.20.12:8080"; break; default: axios.defaults.baseURL = "http://127.0.0.1:3000" } // 設定超時時間和跨域是否允許攜帶憑證 axios.defaults.timeout = 10000; axios.defaults.withCredentials = true; // 設定POST請求頭,告知伺服器請求主體的資料格式(看伺服器要求什麼格式) // 就算是post請求有些人會要求以xxx=xxx&xxx=xxx的形式傳參,這就是x-www-form-urlencoded格式axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'; // 將傳參的json格式的data轉化為xxx=xxx&xxx=xxx axios.defaults.transformRequest = data => { qs.stringify(data)} //設定請求攔截器 // 客戶端傳送請求 ->[請求攔截器] -> 伺服器 // TOKEN校驗(JWT):接收伺服器返回的token,儲存到vuex/本地儲存中,每一次向伺服器發請求,我們應該把token帶上 axios.interceptors.request.use( config =>{ //config表示請求頭的配置項 // 攜帶上token let token = localStorage.getItem('token'); token && (config.headers.Authorization = token); return config; //不返回config的話後端接收一片空白 },error=>{ return Promise.reject(error); }) // 自己設定哪些狀態碼錶示成功,哪些表示失敗(只要是返回2xx或者3xx都算請求成功,響應攔截器就會走第一個,否則走error) axios.default.validateStatus = function (status){ //狀態碼 return /^(2|3)\d{2}$/.test(status); } // 響應攔截器 // 伺服器返回資訊 -> [攔截的統一請求] ->客戶端js獲取到資訊 axios.interceptors.response.use(response=>{ return response.data; //只拿響應主題內容 },error=>{ let { response } = error; if(response){ // 伺服器有返回結果(常用的錯誤狀態碼) switch (response.status){ case 401: //當前請求需要使用者驗證(一般是未登入)(許可權) break; // 一般操作是跳轉路由或者彈出蒙層 case 403: //伺服器已經理解請求,但是拒絕執行它(一般是token過期) localStorage.removeItem('token') // 跳轉到登陸頁 break; case 404: //找不到頁面或者請求失敗,請求所希望得到的資源未被放在伺服器上發現 break; } return Promise.reject(response) }else{ // 伺服器連結果都沒有返回 if(!window.navigator.onLine){ // 斷網處理:可以跳轉到斷網頁面(把路由導進來,重新連線的時候可以go(-1),路由跳轉,路由資訊儲存) return } return Promise.reject(error) //伺服器返回結果都沒有,並且也沒有斷網,此時應該是服務端的問題 } }) export default axios;
fetch封裝庫基本需求
// fetch import qs from 'qs' // 根據環境變數進行介面區分 let baseUrl = ''; let baseURLArr = [ { type:'development', url:'http://127.0.0.1:9000' }, { type:'test', url:'http://192.168.20.15:9000' }, { type:'production', url:'http://api.yanggengzhen.com' } ] baseURLArr.forEach(item=>{ if(process.env.NODE_ENV === item.type){ baseUrl = item.url } }) // 前端請求的時候,傳參的時候轉變為url+? query // request(url,{ // params:{ // } // }) export default function request(url,options={}){ url = baseUrl + url; //請求的url ,配置項,如果不傳,預設為空物件 // get系列請求的處理 !options.methods?options.methods = 'GET':null; if(options.hasOwnProperty('params')){ if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(options.methods)){ //判斷是否是get請求 const ask = url.includes('?')?'&':'?'; url += `${ask}${qs.stringify(params)}` } delete options.params; } // 合併配置項 options = Object.assign({ //允許跨域攜帶資源憑證same-origin同源可以 omit都拒絕 credentials:'include', // 設定請求頭 header:{} },options); options.headers.Accept = 'application/json'; // token的校驗 const token = localStorage.getItem('token'); token && (options.header.Authorization = token); // post請求的處理 if(/^(POST|PUT)$/i.test(options.methods)){ !options.type ? options.type = 'urlencoded' :null; if(options.type === 'urlencoded'){ options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; options.body = qs.stringify(options.body); } if(options.type === 'json'){ options.headers['Content-Type'] = 'application/json'; options.body = JSON.stringify(options.body); } } return fecth(url,options).then(response =>{ // fecth和axios ajax的區別:不論伺服器返回什麼,都會成功觸發.then //返回的結果可能是非200狀態碼 if(!/^(2|3)\d{2}$/.test(response.status)){ switch (response.status) { case 401: // 當前請求需要使用者驗證(一般是未登入) break; case 403: //伺服器已經理解請求,但是拒絕執行它(一般是token過期) break; case 404: //請求失敗,請求所希望得到的資源未被再伺服器上發現 break; } return Promise.reject(response) } }).catch(error => { //斷網處理 if(!window.navigator.onLine){ //斷開網路了。可以讓其跳轉到斷網頁面 return; } return Promise.reject(error) }) }
最後製作成統一介面export出去,再到vue原型鏈上掛載屬性,呼叫即可