Commit 4c6d1fd7 authored by lipengcheng 's avatar lipengcheng

feat: axios封装优化

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