Commit 5e992c84 authored by lipengcheng 's avatar lipengcheng

feat: 新增axios拦截器及其他配置

parent 6cdefb37
...@@ -4,7 +4,7 @@ import router from './router' ...@@ -4,7 +4,7 @@ import router from './router'
import store from './store' import store from './store'
import './registerServiceWorker' import './registerServiceWorker'
import './assets/style/index.scss' import './assets/style/index.scss'
import axios from '@/plugins/axios.js' import requests from '@/plugins/axios.js'
import VueBus from 'vue-bus' import VueBus from 'vue-bus'
import VModal from 'vue-js-modal' import VModal from 'vue-js-modal'
import moment from '@/plugins/moment.js' import moment from '@/plugins/moment.js'
...@@ -28,7 +28,8 @@ Vue.use(VueBus) ...@@ -28,7 +28,8 @@ Vue.use(VueBus)
Vue.use(VModal) Vue.use(VModal)
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.prototype.$http = axios Vue.prototype.$request = requests.request
Vue.prototype.$axios = requests.pureAxios
Vue.prototype.$mt = moment Vue.prototype.$mt = moment
Vue.prototype.$ = utils Vue.prototype.$ = utils
new Vue({ new Vue({
......
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/handleStatus.js' import handleStatus from '@/plugins/axios.handleStatus.js'
// import store from '@/store/index' // import store from '@/store/index'
// import router from '@/router/index.js' // import router from '@/router/index.js'
// import { Message, Notification } from 'element-ui'
/** /**
* 默认配置 * 默认配置
...@@ -15,7 +16,7 @@ axios.defaults.headers['b-laihua-defined-key'] = 'b customized value' ...@@ -15,7 +16,7 @@ axios.defaults.headers['b-laihua-defined-key'] = 'b customized value'
/** /**
* 请求拦截 * 请求拦截
*/ */
axios.interceptors.request.use( const requestInterceptors = axios.interceptors.request.use(
(config) => { (config) => {
// 在发送请求之前做些什么 // 在发送请求之前做些什么
// config.headers.common['cookie-id'] = cookieId // config.headers.common['cookie-id'] = cookieId
...@@ -29,7 +30,7 @@ axios.interceptors.request.use( ...@@ -29,7 +30,7 @@ axios.interceptors.request.use(
/** /**
* 响应拦截 * 响应拦截
*/ */
axios.interceptors.response.use( const responseInterceptors = axios.interceptors.response.use(
(response) => { (response) => {
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleStatus(response))
}, },
...@@ -46,4 +47,17 @@ axios.interceptors.response.use( ...@@ -46,4 +47,17 @@ axios.interceptors.response.use(
} }
) )
// 移除请求拦截器
function removeRequestInterceptors() {
axios.interceptors.request.eject(requestInterceptors)
}
// 移除响应拦截器
function removeResponseInterceptors() {
axios.interceptors.response.eject(responseInterceptors)
}
axios.removeRequestInterceptors = removeRequestInterceptors
axios.removeResponseInterceptors = removeResponseInterceptors
export default axios export default axios
// 移除全局拦截器
// 如果设置了全局拦截器,想取消实例中发出的请求,必须先移除全局拦截器,实例中配置的config.cancelToken属性才会生效
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/handleStatus.js' import handleStatus from '@/plugins/axios.handleStatus.js'
import setOptions from '@/plugins/axios.setOptions.js'
// import store from '@/store/index' // import store from '@/store/index'
// import router from '@/router/index.js' // import router from '@/router/index.js'
// import { Message, Notification } from 'element-ui'
/**
* 默认配置
*/
console.log('axios-process.env:', process.env) console.log('axios-process.env:', process.env)
axios.defaults.baseURL = process.env.VUE_APP_BASEURL
axios.defaults.timeout = 10000 // /**
axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value' // * 默认配置
axios.defaults.headers['b-laihua-defined-key'] = 'b customized value' // */
let pureAxios = setOptions(axios)
let request = setOptions(axios.create())
// 请求中的api
let pendingPool = new Map()
let conf = {}
/** /**
* 请求拦截 * 请求拦截
*/ */
axios.interceptors.request.use( const requestInterceptors = request.interceptors.request.use(
(config) => { (config) => {
request.config = Object.assign({}, config)
console.log('config:', config)
console.log('pendingPool:', pendingPool)
// 在发送请求之前做些什么 // 在发送请求之前做些什么
// config.headers.common['cookie-id'] = cookieId // config.headers.common['cookie-id'] = cookieId
config.cancelToken = new axios.CancelToken((cancelFn) => {
pendingPool.has(config.url) ? cancelFn(`${config.url}请求重复`) : pendingPool.set(config.url, { cancelFn, global: config.global })
})
return config return config
}, },
(err) => { (err) => {
console.log('请求拦截err:', err)
// 对请求错误做些什么 // 对请求错误做些什么
Promise.reject(err) Promise.reject(err)
} }
...@@ -29,21 +45,63 @@ axios.interceptors.request.use( ...@@ -29,21 +45,63 @@ axios.interceptors.request.use(
/** /**
* 响应拦截 * 响应拦截
*/ */
axios.interceptors.response.use( const responseInterceptors = request.interceptors.response.use(
(response) => { (response) => {
const { config } = response
pendingPool.delete(config.url)
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleStatus(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
console.log('响应错误拦截err:', err) console.log('响应拦截err:', err)
console.log('pendingPool2:', pendingPool)
console.log('axios.isCancel(err):', axios.isCancel(err))
// 错误信息err传入isCancel方法,可以判断请求是否被取消 // 错误信息err传入isCancel方法,可以判断请求是否被取消
if (axios.isCancel(err)) { if (axios.isCancel(err)) {
throw new axios.Cancel('cancel request') throw new axios.Cancel(err.message || '请求被主动取消')
} else { } else {
console.log('网络请求失败,请重试:') console.log('网络请求失败,请重试:')
pendingPool.delete(conf.url)
} }
return Promise.reject(err) return Promise.reject(err)
} }
) )
export default axios // 移除全局的请求拦截器
function removeRequestInterceptors() {
request.interceptors.request.eject(requestInterceptors)
}
// 移除全局的响应拦截器
function removeResponseInterceptors() {
request.interceptors.response.eject(responseInterceptors)
}
/**
* // 清除所有pending状态的请求
* @param {Array} whiteList 白名单,里面pending状态的请求不会被取消
* 返回值 被取消了的
*/
function clearPendingPool(whiteList = []) {
if (!pendingPool.size) return
const pendingUrlList = Array.from(pendingPool.keys()).filter((url) => !whiteList.includes(url))
if (!pendingUrlList.length) return
pendingUrlList.forEach((pendingUrl) => {
// 清除掉所有非全局的pending状态下的请求
if (!pendingPool.get(pendingUrl).global) {
pendingPool.get(pendingUrl).cancelFn()
pendingPool.delete(pendingUrl)
}
})
console.log('pendingUrlList:', pendingUrlList)
return pendingUrlList
}
request.removeRequestInterceptors = removeRequestInterceptors
request.removeResponseInterceptors = removeResponseInterceptors
request.clearPendingPool = clearPendingPool
export default {
pureAxios,
request
}
export default (axios, options = {}) => {
// /**
// * 默认配置
// */
// axios.defaults.baseURL = process.env.VUE_APP_BASEURL
// axios.defaults.timeout = 10000
// axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value'
// axios.defaults.headers['b-laihua-defined-key'] = 'b customized value'
const defaultOptions = {
baseURL: process.env.VUE_APP_BASEURL,
timeout: 10000,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'b-laihua-defined-key': 'b customized value',
common: {
'a-laihua-defined-key': 'a customized value'
}
}
}
Object.assign(axios.defaults, defaultOptions, options)
return axios
}
// 参考:https://juejin.im/post/6844904152833736712#heading-5 // 参考:https://juejin.im/post/6844904152833736712#heading-5
import Axios from 'axios' import Axios from 'axios'
import handleStatus from '@/plugins/handleStatus.js' import handleStatus from '@/plugins/axios.handleStatus.js'
const baseURL = '/webapi' // 后台baseUrl const baseURL = '/webapi' // 后台baseUrl
const axios = Axios.create({ const axios = Axios.create({
......
// https://mp.weixin.qq.com/s/v7ku2KYAVW0r4Lmui4JNGA // https://mp.weixin.qq.com/s/v7ku2KYAVW0r4Lmui4JNGA
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/handleStatus.js' import handleStatus from '@/plugins/axios.handleStatus.js'
// import store from '@/store/index' // import store from '@/store/index'
// import router from '@/router/index.js' // import router from '@/router/index.js'
......
import Axios from 'axios' import Axios from 'axios'
import handleStatus from '@/plugins/handleStatus.js' import handleStatus from '@/plugins/axios.handleStatus.js'
// import store from '@/store/index' // import store from '@/store/index'
// import router from '@/router/index.js' // import router from '@/router/index.js'
......
...@@ -6,7 +6,7 @@ import axios from 'axios' ...@@ -6,7 +6,7 @@ import axios from 'axios'
let pendingRequest = [] let pendingRequest = []
/** /**
* 请求的拦截处理 * 请求的拦截处理d
* @param config - 请求的配置项 * @param config - 请求的配置项
*/ */
const handleRequestIntercept = (config) => { const handleRequestIntercept = (config) => {
...@@ -26,7 +26,6 @@ const handleRequestIntercept = (config) => { ...@@ -26,7 +26,6 @@ const handleRequestIntercept = (config) => {
pendingRequest.splice(markIndex, 1) pendingRequest.splice(markIndex, 1)
} }
// (重新)新建针对这次请求的axios的cancelToken标识 // (重新)新建针对这次请求的axios的cancelToken标识
const CancelToken = axios.CancelToken
const source = axios.CancelToken.source() const source = axios.CancelToken.source()
config.cancelToken = source.token config.cancelToken = source.token
// 设置自定义配置requestMark项,主要用于响应拦截中 // 设置自定义配置requestMark项,主要用于响应拦截中
......
// 通过Set数据结构阻止重复请求
// https://blog.csdn.net/Vue2018/article/details/105120206/
import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js'
// import store from '@/store/index'
// import router from '@/router/index.js'
import { Message, Notification } from 'element-ui'
console.log('Message:', Message)
console.log('Notification:', Notification)
/**
* 默认配置
*/
console.log('axios-process.env:', process.env)
axios.defaults.baseURL = process.env.VUE_APP_BASEURL
axios.defaults.timeout = 10000
axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value'
axios.defaults.headers['b-laihua-defined-key'] = 'b customized value'
let pendingList = new Set()
console.log('pendingList:', pendingList)
/**
* 请求拦截
*/
axios.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
// config.headers.common['cookie-id'] = cookieId
config.cancelToken = new axios.CancelToken((c) => {
pendingList.has(config.url) ? c(`${config.url}请求重复`) : pendingList.add(config.url)
})
console.log('pendingList:', pendingList)
return config
},
(err) => {
console.log('err1:', err)
// 对请求错误做些什么
Promise.reject(err)
}
)
/**
* 响应拦截
*/
axios.interceptors.response.use(
(response) => {
const { config } = response
pendingList.delete(config.url)
return Promise.resolve(handleStatus(response))
},
// 对响应错误做点什么
(err) => {
console.log('响应错误拦截err:', err)
// 错误信息err传入isCancel方法,可以判断请求是否被取消
if (axios.isCancel(err)) {
throw new axios.Cancel('cancel request')
} else {
console.log('网络请求失败,请重试:')
}
return Promise.reject(err)
}
)
export default axios
// 移除全局拦截器
// 如果设置了全局拦截器,想取消实例中发出的请求,必须先移除全局拦截器,实例中配置的config.cancelToken属性才会生效
import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js'
// import store from '@/store/index'
// import router from '@/router/index.js'
// import { Message, Notification } from 'element-ui'
/**
* 默认配置
*/
console.log('axios-process.env:', process.env)
axios.defaults.baseURL = process.env.VUE_APP_BASEURL
axios.defaults.timeout = 10000
axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value'
axios.defaults.headers['b-laihua-defined-key'] = 'b customized value'
// 请求中的api列表
let pendingList = new Set()
/**
* 请求拦截
*/
const requestInterceptors = axios.interceptors.request.use(
(config) => {
console.log('config:', config)
// 在发送请求之前做些什么
// config.headers.common['cookie-id'] = cookieId
config.cancelToken = new axios.CancelToken((c) => {
pendingList.has(config.url) ? c(`${config.url}请求重复`) : pendingList.add(config.url)
})
return config
},
(err) => {
console.log('err1:', err)
// 对请求错误做些什么
Promise.reject(err)
}
)
/**
* 响应拦截
*/
const responseInterceptors = axios.interceptors.response.use(
(response) => {
const { config } = response
pendingList.delete(config.url)
return Promise.resolve(handleStatus(response))
},
// 对响应错误做点什么
(err) => {
console.log('响应错误拦截err:', err)
// 错误信息err传入isCancel方法,可以判断请求是否被取消
if (axios.isCancel(err)) {
throw new axios.Cancel('cancel request')
} else {
console.log('网络请求失败,请重试:')
}
return Promise.reject(err)
}
)
// 移除全局的请求拦截器
function removeRequestInterceptors() {
axios.interceptors.request.eject(requestInterceptors)
}
// 移除全局的响应拦截器
function removeResponseInterceptors() {
axios.interceptors.response.eject(responseInterceptors)
}
axios.removeRequestInterceptors = removeRequestInterceptors
axios.removeResponseInterceptors = removeResponseInterceptors
export default axios
// 取消重复请求的基础上
// 新增移除所有pending状态请求的方法,并对外暴露,可用于路由切换时取消之前所有请求
import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js'
// import store from '@/store/index'
// import router from '@/router/index.js'
// import { Message, Notification } from 'element-ui'
/**
* 默认配置
*/
console.log('axios-process.env:', process.env)
axios.defaults.baseURL = process.env.VUE_APP_BASEURL
axios.defaults.timeout = 10000
axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value'
axios.defaults.headers['b-laihua-defined-key'] = 'b customized value'
// 请求中的api
let pendingPool = new Map()
axios.config = {}
/**
* 请求拦截
*/
const requestInterceptors = axios.interceptors.request.use(
(config) => {
axios.config = Object.assign({}, config)
console.log('config:', config)
console.log('pendingPool:', pendingPool)
// 在发送请求之前做些什么
// config.headers.common['cookie-id'] = cookieId
config.cancelToken = new axios.CancelToken((cancelFn) => {
pendingPool.has(config.url) ? cancelFn(`${config.url}请求重复`) : pendingPool.set(config.url, { cancelFn, global: config.global })
console.log('pendingPool.has(config.url):', pendingPool.has(config.url))
})
return config
},
(err) => {
console.log('请求拦截err:', err)
// 对请求错误做些什么
Promise.reject(err)
}
)
/**
* 响应拦截
*/
const responseInterceptors = axios.interceptors.response.use(
(response) => {
const { config } = response
pendingPool.delete(config.url)
return Promise.resolve(handleStatus(response))
},
// 对响应错误做点什么
(err) => {
console.log('响应拦截err:', err)
console.log('pendingPool2:', pendingPool)
console.log('axios.isCancel(err):', axios.isCancel(err))
// 错误信息err传入isCancel方法,可以判断请求是否被取消
if (axios.isCancel(err)) {
throw new axios.Cancel(err.message || '请求被主动取消')
} else {
console.log('网络请求失败,请重试:')
pendingPool.delete(axios.config.url)
}
return Promise.reject(err)
}
)
// 移除全局的请求拦截器
function removeRequestInterceptors() {
axios.interceptors.request.eject(requestInterceptors)
}
// 移除全局的响应拦截器
function removeResponseInterceptors() {
axios.interceptors.response.eject(responseInterceptors)
}
// 清除所有pending状态的请求
function clearPendingPool() {
if (!pendingPool.size) return
const pendingUrlList = Array.from(pendingPool.keys())
pendingUrlList.forEach((pendingUrl) => {
console.log('pendingUrl:', pendingUrl)
// 清除掉所有非全局的pending状态下的请求
if (!pendingPool.get(pendingUrl).global) {
pendingPool.get(pendingUrl).cancelFn()
pendingPool.delete(pendingUrl)
}
})
}
axios.removeRequestInterceptors = removeRequestInterceptors
axios.removeResponseInterceptors = removeResponseInterceptors
axios.clearPendingPool = clearPendingPool
export default axios
import Vue from 'vue' import Vue from 'vue'
import VueRouter from 'vue-router' import VueRouter from 'vue-router'
import store from '@/store/index.js' import store from '@/store/index.js'
import requests from '@/plugins/axios.js'
Vue.use(VueRouter) Vue.use(VueRouter)
let routes = [] let routes = []
...@@ -56,6 +56,9 @@ const router = new VueRouter({ ...@@ -56,6 +56,9 @@ const router = new VueRouter({
// 路由全局前置守卫 // 路由全局前置守卫
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
// 路由变化时取消所有非全局的pending状态的请求
requests.request.clearPendingPool()
// 未登录情况下访问的页面需要登录,自动跳转到指定页面(登录页)
if (to.meta.needAuth && !store.getters['authed']) next({ name: 'page2' }) if (to.meta.needAuth && !store.getters['authed']) next({ name: 'page2' })
else next() else next()
}) })
......
...@@ -24,14 +24,24 @@ ...@@ -24,14 +24,24 @@
<use xlink:href="#icon-14"></use> <use xlink:href="#icon-14"></use>
</svg> </svg>
<div <div
style="width:50px;height: 20px;" style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px"
@click="aaa"> @click="aaa">
1111 发送请求 d
</div> </div>
<div <div
style="width:50px;height: 20px;" style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px"
@click="bbb"> @click="bbb">
2222 取消请求
</div>
<div
style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px"
@click="ccc">
实例中取消请求1
</div>
<div
style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px"
@click="ccc1">
实例中取消请求2
</div> </div>
</div> </div>
</template> </template>
...@@ -48,26 +58,57 @@ export default { ...@@ -48,26 +58,57 @@ export default {
mounted() {}, mounted() {},
methods: { methods: {
ttt() { ttt() {
console.log('this.axios.CancelToken:', this.$http.CancelToken)
this.$store.dispatch('testAction') this.$store.dispatch('testAction')
}, },
async aaa() { async aaa() {
let CancelToken = this.$http.CancelToken // this.$request.removeRequestInterceptors()
this.source = this.$http.CancelToken.source() // let CancelToken = this.$request.CancelToken
this.cancelObj = {} // this.source = CancelToken.source()
let result = await this.$http.get('/home/banner?type=1&category=18', { let params = {
cancelToken: new CancelToken((c) => { a: 1,
this.cancelObj.url = '///' type: 1,
this.cancelObj.cancel = c category: 18
}
let result = await this.$request
.get('/home/banner', {
params
// global: true
// cancelToken: this.source.token
})
.catch((err) => {
console.log('实例请求出错:', err, err.message)
}) })
})
console.log('this.cancelObj:', this.cancelObj)
console.log('result:', result) console.log('result:', result)
}, },
bbb() { async bbb() {
console.log('this.source:', this.source)
// this.source.cancel('333333333') // this.source.cancel('333333333')
this.cancelObj.cancel() // this.cancelObj.cancel()
this.$request.clearPendingPool()
// this.aaa()
},
async ccc() {
let source = this.$axios.CancelToken.source()
let result = this.$axios.get('/home/banner', {
cancelToken: source.token
})
console.log('result:', result)
setTimeout(() => {
source.cancel()
}, 500)
},
async ccc1() {
let cancelFn
this.$axios
.get('/home/banner', {
cancelToken: new this.$axios.CancelToken((c) => (cancelFn = c))
})
.then((data) => {
console.log('data:', data)
})
.catch((err) => console.log('err:', err))
setTimeout(() => {
cancelFn()
}, 500)
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment