Commit 4c6d1fd7 authored by lipengcheng 's avatar lipengcheng

feat: axios封装优化

'
parent edf68d9a
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
* let xx = await this.$api.getBanner({}, {timeout: 1000, headers:{ aaa: 111 }}) * let xx = await this.$api.getBanner({}, {timeout: 1000, headers:{ aaa: 111 }})
*/ */
import { request } from '@/plugins/axios/index' import { request } from '@/plugins/axios/index'
import qs from 'qs' // import qs from 'qs'
console.log('qs:', qs)
const apiMap = { const apiMap = {
getBanner: { method: 'get', url: '/home/banner' }, getBanner: { method: 'get', url: '/home/banner' },
...@@ -31,7 +30,8 @@ function injectRequest(apiObj) { ...@@ -31,7 +30,8 @@ function injectRequest(apiObj) {
return request({ return request({
method, method,
url, url,
[keyName]: method === 'POST' ? qs.stringify(dataOrParams) : dataOrParams, // [keyName]: method === 'POST' ? qs.stringify(dataOrParams) : dataOrParams,
[keyName]: dataOrParams,
...Object.assign(config || {}, instanceConf) ...Object.assign(config || {}, instanceConf)
}) })
} }
......
...@@ -29,7 +29,7 @@ Vue.use(VModal) ...@@ -29,7 +29,7 @@ Vue.use(VModal)
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.prototype.$request = requests.request Vue.prototype.$request = requests.request
Vue.prototype.$axios = requests.pureAxios Vue.prototype.$pureRequest = requests.pureRequest
Vue.prototype.$api = api Vue.prototype.$api = api
Vue.prototype.$mt = moment Vue.prototype.$mt = moment
Vue.prototype.$ = utils Vue.prototype.$ = utils
......
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.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' // import { Message, Notification } from 'element-ui'
...@@ -31,7 +31,7 @@ const requestInterceptors = axios.interceptors.request.use( ...@@ -31,7 +31,7 @@ const requestInterceptors = axios.interceptors.request.use(
*/ */
const responseInterceptors = axios.interceptors.response.use( const responseInterceptors = axios.interceptors.response.use(
(response) => { (response) => {
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
export default (err) => {
const { response } = err
if (!response.status) {
err.code = ''
err.message = '有response但没有response.status的情况'
}
err.code = response.status
switch (response.status) {
case 200:
err.message = '错误响应也会有状态码为200的情况'
break
case 400:
err.message = '请求错误(400)'
break
case 401:
err.message = '未授权,请重新登录(401)'
break
case 403:
err.message = '拒绝访问(403)'
break
case 404:
err.message = '请求出错(404)'
break
case 408:
err.message = '请求超时(408)'
break
case 500:
err.message = '服务器错误(500)'
break
case 501:
err.message = '服务未实现(501)'
break
case 502:
err.message = '网络错误(502)'
break
case 503:
err.message = '服务不可用(503)'
break
case 504:
err.message = '网络超时(504)'
break
case 505:
err.message = 'HTTP版本不受支持(505)'
break
default:
err.message = `连接出错,状态码:(${err.response.status})!`
}
return err
}
// 处理响应错误码 // 处理响应错误码
export default (response) => { export default (response) => {
console.log('response:', response)
const status = response.status const status = response.status
// 如果http响应状态码response.status正常,则直接返回数据 // 如果http响应状态码response.status正常,则直接返回数据
if ((status >= 200 && status <= 300) || status === 304) { if ((status >= 200 && status <= 300) || status === 304) {
return response.data return response
} else { }
// 判断后端返回的code // status不正常的话,根据与后端约定好的code,做出对应的提示与处理
let errMsg = '' // 返回一个带有code和message属性的对象
else {
const code = parseInt(response.data && response.data.code) const code = parseInt(response.data && response.data.code)
const msg = (response.data || {}).msg // msg为服务端返回的错误信息,字段名自定义,此处以msg为例
console.log('msg:', msg) let message = (response.data || {}).msg
switch (code) { switch (code) {
case 400: case 400:
break break
case 4001: case 4001:
if (process.server) return if (process.server) return
errMsg = '登录设备数量超出限制' message = message || '登录设备数量超出限制'
// store.commit('savehttpResult', { res: response.data }) // store.commit('savehttpResult', { res: response.data })
break break
case 403: case 403:
errMsg = '未登录' message = message || '未登录'
// store.commit('changeLogin', {})
break break
case 404: case 404:
errMsg = '请求地址错误' message = message || '请求地址错误'
// store.commit('changeLogin', {})
break break
case 412: case 412:
errMsg = '未找到有效session' message = message || '未找到有效session'
break
case 408:
errMsg = '请求超时'
break
case 500:
errMsg = '服务器内部错误'
break
case 501:
errMsg = '服务未实现'
break
case 502:
errMsg = '网关错误'
break
case 503:
errMsg = '服务不可用'
break
case 504:
errMsg = '网关超时'
break
case 505:
errMsg = 'HTTP版本不受支持'
break break
default: default:
// errMsg = err.response.data.msg // message = message || err.response.data.msg
break break
} }
return { return {
code, code,
errMsg message
} }
} }
} }
export default (axios, options = {}) => { export default (axios, config = {}) => {
// /** // /**
// * 默认配置 // * 默认配置
// */ // */
...@@ -7,7 +7,7 @@ export default (axios, options = {}) => { ...@@ -7,7 +7,7 @@ export default (axios, options = {}) => {
// axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value' // axios.defaults.headers.common['a-laihua-defined-key'] = 'a customized value'
// axios.defaults.headers['b-laihua-defined-key'] = 'b customized value' // axios.defaults.headers['b-laihua-defined-key'] = 'b customized value'
const defaultOptions = { const defaultConfig = {
baseURL: process.env.VUE_APP_BASEURL, baseURL: process.env.VUE_APP_BASEURL,
timeout: 10000, timeout: 10000,
headers: { headers: {
...@@ -19,6 +19,6 @@ export default (axios, options = {}) => { ...@@ -19,6 +19,6 @@ export default (axios, options = {}) => {
} }
} }
Object.assign(axios.defaults, defaultOptions, options) Object.assign(axios.defaults, defaultConfig, config)
return axios 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/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.js'
const baseURL = '/webapi' // 后台baseUrl const baseURL = '/webapi' // 后台baseUrl
const axios = Axios.create({ const axios = Axios.create({
...@@ -50,7 +50,7 @@ axios.interceptors.request.use( ...@@ -50,7 +50,7 @@ axios.interceptors.request.use(
axios.interceptors.response.use( axios.interceptors.response.use(
(response) => { (response) => {
removePending(response.config) removePending(response.config)
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
// 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/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.js'
// import store from '@/store/index' // import store from '@/store/index'
// import router from '@/router/index.js' // import router from '@/router/index.js'
...@@ -50,7 +50,7 @@ axios.interceptors.request.use( ...@@ -50,7 +50,7 @@ axios.interceptors.request.use(
axios.interceptors.response.use( axios.interceptors.response.use(
(response) => { (response) => {
removePendingAjax(response.config) removePendingAjax(response.config)
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
import Axios from 'axios' import Axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.js'
// import store from '@/store/index' // import store from '@/store/index'
// import router from '@/router/index.js' // import router from '@/router/index.js'
...@@ -58,7 +58,7 @@ axios.interceptors.request.use( ...@@ -58,7 +58,7 @@ axios.interceptors.request.use(
*/ */
axios.interceptors.response.use( axios.interceptors.response.use(
(response) => { (response) => {
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// https://blog.csdn.net/Vue2018/article/details/105120206/ // https://blog.csdn.net/Vue2018/article/details/105120206/
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.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' import { Message, Notification } from 'element-ui'
...@@ -46,7 +46,7 @@ axios.interceptors.response.use( ...@@ -46,7 +46,7 @@ axios.interceptors.response.use(
(response) => { (response) => {
const { config } = response const { config } = response
pendingList.delete(config.url) pendingList.delete(config.url)
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// 如果设置了全局拦截器,想取消实例中发出的请求,必须先移除全局拦截器,实例中配置的config.cancelToken属性才会生效 // 如果设置了全局拦截器,想取消实例中发出的请求,必须先移除全局拦截器,实例中配置的config.cancelToken属性才会生效
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.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' // import { Message, Notification } from 'element-ui'
...@@ -45,7 +45,7 @@ const responseInterceptors = axios.interceptors.response.use( ...@@ -45,7 +45,7 @@ const responseInterceptors = axios.interceptors.response.use(
(response) => { (response) => {
const { config } = response const { config } = response
pendingList.delete(config.url) pendingList.delete(config.url)
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// 新增移除所有pending状态请求的方法,并对外暴露,可用于路由切换时取消之前所有请求 // 新增移除所有pending状态请求的方法,并对外暴露,可用于路由切换时取消之前所有请求
import axios from 'axios' import axios from 'axios'
import handleStatus from '@/plugins/axios.handleStatus.js' import handleResponse from '@/plugins/axios.handleResponse.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' // import { Message, Notification } from 'element-ui'
...@@ -49,7 +49,7 @@ const responseInterceptors = axios.interceptors.response.use( ...@@ -49,7 +49,7 @@ const responseInterceptors = axios.interceptors.response.use(
(response) => { (response) => {
const { config } = response const { config } = response
pendingPool.delete(config.url) pendingPool.delete(config.url)
return Promise.resolve(handleStatus(response)) return Promise.resolve(handleResponse(response))
}, },
// 对响应错误做点什么 // 对响应错误做点什么
(err) => { (err) => {
......
...@@ -2,29 +2,25 @@ ...@@ -2,29 +2,25 @@
// 如果设置了全局拦截器,想取消实例中发出的请求,必须先移除全局拦截器,实例中配置的config.cancelToken属性才会生效 // 如果设置了全局拦截器,想取消实例中发出的请求,必须先移除全局拦截器,实例中配置的config.cancelToken属性才会生效
import axios from 'axios' import axios from 'axios'
// import handleStatus from '@/plugins/axios/axios.handleStatus.js' import handleResponse from '@/plugins/axios/axios.handleResponse.js'
import setOptions from '@/plugins/axios/axios.setOptions.js' import handleError from '@/plugins/axios/axios.handleError.js'
import setConfig from '@/plugins/axios/axios.setConfig.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' // import { Message } from 'element-ui'
// const tip = msg => { /**
// Message({ * pureRequest是只在axios基础上更改了请求配置。
// message: msg, * 而request是基于axios创建的实例,实例只有常见的数据请求方法,没有axios.isCancel/ axios.CancelToken等方法,
// duration: 1000, * 也就是没有**取消请求**和**批量请求**的方法。
// type: "error" * 所以如果需要在实例中调用取消某个请求的方法(例如取消上传),请用pureRequest。
// }); */
// } let pureRequest = setConfig(axios)
let request = setConfig(axios.create())
// /**
// * 默认配置
// */
let pureAxios = setOptions(axios)
let request = setOptions(axios.create())
// 请求中的api // 请求中的api
let pendingPool = new Map() let pendingPool = new Map()
// 当前请求的config,用于此请求的响应异常后在pendingPool中将其删除
let conf = {} let conf = {}
/** /**
...@@ -53,89 +49,46 @@ const requestInterceptors = request.interceptors.request.use( ...@@ -53,89 +49,46 @@ const requestInterceptors = request.interceptors.request.use(
const responseInterceptors = request.interceptors.response.use( const responseInterceptors = request.interceptors.response.use(
(response) => { (response) => {
console.log('响应response suc:', response) console.log('响应response suc:', response)
const { config } = response const { config } = response
pendingPool.delete(config.url) pendingPool.delete(config.url)
return response.status === 200 ? Promise.resolve(response) : Promise.reject(response) return Promise.resolve(handleResponse(response))
// return Promise.resolve(handleStatus(response))
}, },
// 对响应错误做点什么 // 对异常响应处理
(err) => { (err) => {
console.log('响应拦截err:', err) console.log('响应拦截err1:', err)
console.log('err.stack:', err.stack) console.log('err.stack:', err.stack)
console.log('err.response:', err.response) console.log('err.response:', err.response)
console.log('err.response.status:', err.response.status) // console.log('err.response.status:', err.response.status)
// console.log('err.response.data:',err.response.data) // console.log('err.response.data:',err.response.data)
console.log('err.response.data.code:', err.response.data.code) // console.log('err.response.data.code:', err.response.data.code)
console.log('err.response.data.message:', err.response.data.message) // console.log('err.response.data.message:', err.response.data.message)
console.log('axios.isCancel(err):', axios.isCancel(err)) console.log('axios.isCancel(err):', axios.isCancel(err))
// let {response} = err console.log('Array.from(pendingPool.keys()):', Array.from(pendingPool.keys()))
// if (response) { pendingPool.delete(conf.url)
// // 请求已发出,但是不在2xx的范围
// errorHandle(response.status, response.data.message);
// return Promise.reject(response);
// } else {
// // 处理断网的情况
// // eg:请求超时或断网时,更新state的network状态
// // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
// // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
// store.commit('changeNetwork', false);
// }
if (err.reponse && err.response.status) { if (!err) return Promise.reject(err)
switch (err.response.status) {
case 400: if (err.response) {
err.message = '请求错误(400)' err = handleError(err)
break
case 401:
err.message = '未授权,请重新登录(401)'
break
case 403:
err.message = '拒绝访问(403)'
break
case 404:
err.message = '请求出错(404)'
break
case 408:
err.message = '请求超时(408)'
break
case 500:
err.message = '服务器错误(500)'
break
case 501:
err.message = '服务未实现(501)'
break
case 502:
err.message = '网络错误(502)'
break
case 503:
err.message = '服务不可用(503)'
break
case 504:
err.message = '网络超时(504)'
break
case 505:
err.message = 'HTTP版本不受支持(505)'
break
default:
err.message = `连接出错(${err.response.status})!`
}
} }
// 获取不到状态码的情况 // 没有response(没有状态码)的情况
// eg: 超时;断网;请求重复被取消;主动取消请求;
else { else {
console.log('else err===:', err)
// 错误信息err传入isCancel方法,可以判断请求是否被取消 // 错误信息err传入isCancel方法,可以判断请求是否被取消
if (axios.isCancel(err)) { if (axios.isCancel(err)) {
throw new axios.Cancel(err.message || '请求被主动取消') throw new axios.Cancel(err.message || '请求被主动取消')
} }
if (err && err.stack.includes('timeout')) { if (err.stack.includes('timeout')) {
// 超时的情况下err.response为undefined // 超时的情况下err.response为undefined
err.message = '请求超时!' err.message = '请求超时!'
} }
err.message = '连接服务器失败!' err.message = '连接服务器失败!'
} }
pendingPool.delete(conf.url)
return Promise.reject(err) return Promise.reject(err)
} }
) )
...@@ -175,7 +128,7 @@ request.removeResponseInterceptors = removeResponseInterceptors ...@@ -175,7 +128,7 @@ request.removeResponseInterceptors = removeResponseInterceptors
request.clearPendingPool = clearPendingPool request.clearPendingPool = clearPendingPool
// export default{ // export default{
// pureAxios, // pureRequest,
// request // request
// } // }
export { pureAxios, request } export { pureRequest, request }
<template> <template>
<div class="comp-bao2"> <div class="comp-bao2">
<h1 @click="ttt()"> <h1>
home home
</h1> </h1>
<div <div
...@@ -33,15 +33,29 @@ ...@@ -33,15 +33,29 @@
@click="bbb"> @click="bbb">
取消请求 取消请求
</div> </div>
<div <div style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px">
style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px" <button
@click="ccc"> class="btn"
实例中取消请求1 @click="ccc()">
实例中取消请求写法1
</button>
<button
class="btn"
@click="cancelCcc()">
取消请求1
</button>
</div> </div>
<div <div style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px">
style="width:auto;height: 100px;border: 1px solid pink;margin-top:10px" <button
@click="ccc1"> class="btn"
实例中取消请求2 @click="ccc1()">
实例中取消请求写法2
</button>
<button
class="btn"
@click="cancelCcc1()">
取消请求2
</button>
</div> </div>
</div> </div>
</template> </template>
...@@ -51,25 +65,29 @@ export default { ...@@ -51,25 +65,29 @@ export default {
data() { data() {
return { return {
source: {}, source: {},
cancelObj: {} cancelObj: {},
source1: {},
source2: {},
cancelFn: ''
} }
}, },
created() {}, created() {},
async mounted() { async mounted() {
let xx = await this.$api.getBanner( // let xx = await this.$api.getBanner(
{ pageSize: 20, pIndex: 2 }, // { pageSize: 20, pIndex: 2 },
{ // {
// timeout:1 // // timeout:1
} // }
) // )
console.log('xx:', xx) // console.log('xx:', xx)
let vv = await this.$api.login({ account: '18038018084', psw: '123456' }) // let vv = await this.$api.login({ account: '18038018084', psw: '123456' }).catch(eee => {
console.log('vv:', vv) // console.log('eee:',eee)
// })
// console.log('vv:', vv)
this.$api.getBanner()
this.$api.getBanner()
}, },
methods: { methods: {
ttt() {
this.$store.dispatch('testAction')
},
async aaa() { async aaa() {
// this.$request.removeRequestInterceptors() // this.$request.removeRequestInterceptors()
// let CancelToken = this.$request.CancelToken // let CancelToken = this.$request.CancelToken
...@@ -96,29 +114,32 @@ export default { ...@@ -96,29 +114,32 @@ export default {
this.$request.clearPendingPool() this.$request.clearPendingPool()
// this.aaa() // this.aaa()
}, },
// 实例中取消请求写法1
async ccc() { async ccc() {
let source = this.$axios.CancelToken.source() this.source1 = this.$pureRequest.CancelToken.source()
let result = this.$axios.get('/home/banner', { let result = await this.$pureRequest
cancelToken: source.token .get('/home/banner', {
cancelToken: this.source1.token
}) })
.catch((err) => console.log('11 err:', err))
console.log('result:', result) console.log('result:', result)
setTimeout(() => {
source.cancel()
}, 500)
}, },
cancelCcc() {
this.source1.cancel('xxxxx')
},
// 实例中取消请求写法2
async ccc1() { async ccc1() {
let cancelFn this.$pureRequest
this.$axios
.get('/home/banner', { .get('/home/banner', {
cancelToken: new this.$axios.CancelToken((c) => (cancelFn = c)) cancelToken: new this.$pureRequest.CancelToken((c) => (this.cancelFn = c))
}) })
.then((data) => { .then((data) => {
console.log('data:', data) console.log('data:', data)
}) })
.catch((err) => console.log('err:', err)) .catch((err) => console.log('err:', err))
setTimeout(() => { },
cancelFn() cancelCcc1() {
}, 500) this.cancelFn('yyyyy')
}, },
// get写法1 // get写法1
async getMethod1() { async getMethod1() {
...@@ -172,4 +193,9 @@ export default { ...@@ -172,4 +193,9 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
/* @import url(); 引入css类 */ /* @import url(); 引入css类 */
.btn {
padding: 10px;
display: block;
cursor: pointer;
}
</style> </style>
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