vue axios基于常見(jiàn)業(yè)務(wù)場(chǎng)景的二次封裝的實(shí)現(xiàn)
axios
axios 是一個(gè)基于 promise 的 HTTP 庫(kù),可以用在瀏覽器和 node.js 中。
在前端框架中的應(yīng)用也是特別廣泛,不管是vue還是react,都有很多項(xiàng)目用axios作為網(wǎng)絡(luò)請(qǐng)求庫(kù)。
我在最近的幾個(gè)項(xiàng)目中都有使用axios,并基于axios根據(jù)常見(jiàn)的業(yè)務(wù)場(chǎng)景封裝了一個(gè)通用的request服務(wù)。
npm:
$ npm install axios
bower:
$ bower install axios
Using cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
業(yè)務(wù)場(chǎng)景:
- 全局請(qǐng)求配置。
- get,post,put,delete等請(qǐng)求的promise封裝。
- 全局請(qǐng)求狀態(tài)管理,供加載動(dòng)畫(huà)等使用。
- 路由跳轉(zhuǎn)取消當(dāng)前頁(yè)面請(qǐng)求。
- 請(qǐng)求攜帶token,權(quán)限錯(cuò)誤統(tǒng)一管理。
默認(rèn)配置
定義全局的默認(rèn)配置
axios.defaults.timeout = 10000 //超時(shí)取消請(qǐng)求 axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' axios.defaults.baseURL = process.env.BASE_URL
自定義配置(非常見(jiàn)業(yè)務(wù)場(chǎng)景,僅作介紹)
// 創(chuàng)建實(shí)例時(shí)設(shè)置配置的默認(rèn)值 var instance = axios.create({ baseURL: 'https://api.another.com' }); // 在實(shí)例已創(chuàng)建后修改默認(rèn)值 instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
優(yōu)先級(jí):自定義配置 > 默認(rèn)配置
請(qǐng)求及響應(yīng)攔截器
請(qǐng)求攔截器
// 請(qǐng)求列表 const requestList = [] axios.interceptors.request.use((config) => { //1.將當(dāng)前請(qǐng)求的URL添加進(jìn)請(qǐng)求列表數(shù)組 requestList.push(config.url) //2.請(qǐng)求開(kāi)始,改變loading狀態(tài)供加載動(dòng)畫(huà)使用 store.dispatch('changeGlobalState', {loading: true}) //3.從store中獲取token并添加到請(qǐng)求頭供后端作權(quán)限校驗(yàn) const token = store.getters.userInfo.token if (token) { config.headers.token = token } return config }, function (error) { return Promise.reject(error) })
1.請(qǐng)求攔截器中將所有請(qǐng)求的url添加進(jìn)請(qǐng)求列表變量,為取消請(qǐng)求及l(fā)oading狀態(tài)管理做準(zhǔn)備
2.請(qǐng)求一旦開(kāi)始,就可以開(kāi)啟動(dòng)畫(huà)加載效果。
3.用戶登錄后可以在請(qǐng)求頭中攜帶token做權(quán)限校驗(yàn)使用。
響應(yīng)攔截器
axios.interceptors.response.use(function (response) { // 1.將當(dāng)前請(qǐng)求中請(qǐng)求列表中刪除 requestList.splice(requestList.findIndex(item => item === response.config.url), 1) // 2.當(dāng)請(qǐng)求列表為空時(shí),更改loading狀態(tài) if (requestList.length === 0) { store.dispatch('changeGlobalState', {loading: false}) } // 3.統(tǒng)一處理權(quán)限認(rèn)證錯(cuò)誤管理 if (response.data.code === 900401) { window.ELEMENT.Message.error('認(rèn)證失效,請(qǐng)重新登錄!', 1000) router.push('/login') } return response }, function (error) { // 4.處理取消請(qǐng)求 if (axios.isCancel(error)) { requestList.length = 0 store.dispatch('changeGlobalState', {loading: false}) throw new axios.Cancel('cancel request') } else { // 5.處理網(wǎng)絡(luò)請(qǐng)求失敗 window.ELEMENT.Message.error('網(wǎng)絡(luò)請(qǐng)求失敗', 1000) } return Promise.reject(error) })
1.響應(yīng)返回后將相應(yīng)的請(qǐng)求從請(qǐng)求列表中刪除
2.當(dāng)請(qǐng)求列表為空時(shí),即所有請(qǐng)求結(jié)束,加載動(dòng)畫(huà)結(jié)束
3.權(quán)限認(rèn)證報(bào)錯(cuò)統(tǒng)一攔截處理
4.取消請(qǐng)求的處理需要結(jié)合其他代碼說(shuō)明
5.由于項(xiàng)目后端并沒(méi)有采用RESTful風(fēng)格的接口請(qǐng)求,200以外都?xì)w為網(wǎng)絡(luò)請(qǐng)求失敗
promise封裝及取消請(qǐng)求
const CancelToken = axios.CancelToken //cancel token列表 let sources = [] const request = function (url, params, config, method) { return new Promise((resolve, reject) => { axios[method](url, params, Object.assign({}, config, { //1.通過(guò)將執(zhí)行程序函數(shù)傳遞給CancelToken構(gòu)造函數(shù)來(lái)創(chuàng)建cancel token cancelToken: new CancelToken(function executor (c) { //2.將cancel token存入列表 sources.push(c) }) })).then(response => { resolve(response.data) }, err => { if (err.Cancel) { console.log(err) } else { reject(err) } }).catch(err => { reject(err) }) }) } const post = (url, params, config = {}) => { return request(url, params, config, 'post') } const get = (url, params, config = {}) => { return request(url, params, config, 'get') } //3.導(dǎo)出cancel token列表供全局路由守衛(wèi)使用 export {sources, post, get}
1.axios cancel token API
2.存入需要取消的請(qǐng)求列表導(dǎo)出給導(dǎo)航守衛(wèi)使用
3.router.js
... import { sources } from '../service/request' ... router.beforeEach((to, from, next) => { document.title = to.meta.title || to.name //路由發(fā)生變化時(shí)取消當(dāng)前頁(yè)面網(wǎng)絡(luò)請(qǐng)求 sources.forEach(item => { item() }) sources.length = 0 next() })
request.js完整代碼:
// 引入網(wǎng)絡(luò)請(qǐng)求庫(kù) https://github.com/axios/axios import axios from 'axios' import store from '../store' import router from '../router' // axios.defaults.timeout = 10000 const requestList = [] axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' axios.defaults.baseURL = process.env.BASE_URL // 自定義攔截器 axios.interceptors.request.use((config) => { requestList.push(config.url) store.dispatch('changeGlobalState', {loading: true}) const token = store.getters.userInfo.token if (token) { config.headers.token = token } return config }, function (error) { return Promise.reject(error) }) axios.interceptors.response.use(function (response) { requestList.splice(requestList.findIndex(item => item === response.config.url), 1) if (requestList.length === 0) { store.dispatch('changeGlobalState', {loading: false}) } if (response.data.code === 900401) { window.$toast.error('認(rèn)證失效,請(qǐng)重新登錄!', 1000) router.push('/login') } return response }, function (error) { requestList.length = 0 store.dispatch('changeGlobalState', {loading: false}) if (axios.isCancel(error)) { throw new axios.Cancel('cancel request') } else { window.$toast.error('網(wǎng)絡(luò)請(qǐng)求失??!', 1000) } return Promise.reject(error) }) const CancelToken = axios.CancelToken let sources = [] const request = function (url, params, config, method) { return new Promise((resolve, reject) => { axios[method](url, params, Object.assign(config, { cancelToken: new CancelToken(function executor (c) { sources.push(c) }) })).then(response => { resolve(response.data) }, err => { reject(err) }).catch(err => { reject(err) }) }) } const post = (url, params, config = {}) => { return request(url, params, config, 'post') } const get = (url, params, config = {}) => { return request(url, params, config, 'get') } export {sources, post, get}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue-cli2.0轉(zhuǎn)3.0之項(xiàng)目搭建的詳細(xì)步驟
這篇文章主要介紹了vue-cli2.0轉(zhuǎn)3.0之項(xiàng)目搭建的詳細(xì)步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12vue中計(jì)算屬性和方法的區(qū)別及說(shuō)明
這篇文章主要介紹了vue中計(jì)算屬性和方法的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09Vue tagsview實(shí)現(xiàn)多頁(yè)簽導(dǎo)航功能流程詳解
基本上后臺(tái)管理系統(tǒng)都需要有多頁(yè)簽的功能,但是因?yàn)橐恍┠_手架項(xiàng)目基本都把這個(gè)功能給集成好了,導(dǎo)致在學(xué)習(xí)或者修改的時(shí)候不知道該如何下手。今天這篇文章就來(lái)聊一聊,vue-element-admin項(xiàng)目是如何實(shí)現(xiàn)多頁(yè)簽功能的2022-09-09vue3發(fā)送驗(yàn)證碼倒計(jì)時(shí)功能的實(shí)現(xiàn)(防止連點(diǎn)、封裝復(fù)用)
這篇文章主要介紹了vue3發(fā)送驗(yàn)證碼倒計(jì)時(shí)功能的實(shí)現(xiàn)(防止連點(diǎn)、封裝復(fù)用),實(shí)現(xiàn)思路是點(diǎn)擊發(fā)送驗(yàn)證碼,驗(yàn)證碼倒計(jì)時(shí),校驗(yàn)手機(jī)號(hào)是否正常等一系列操作,本文通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01Vue from-validate 表單驗(yàn)證的示例代碼
本篇文章主要介紹了Vue from-validate 表單驗(yàn)證的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09