这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战
背景
本文所说的request请求即前端请求后端数据所用到的request请求,前后端的交互由来已久,什么jsonp了,ajax了,方式有很多中,今天我就说目前在项目中真正用到的东西,也就是基于axios封装的request请求。下面上代码,一步步的来分析
import axios from 'axios'
import store from '@/store'
import storage from 'store'
import notification from 'ant-design-vue/es/notification' //antdesign中的通知提醒框,如果你用的elementui可以自行更换
import qs from 'qs' //qs库,作用:将url中的参数转化为对象,将对象转为url参数形式
import { ACCESS_TOKEN } from '@/store/mutation-types' // 项目中的token
// 创建 axios 实例
const request = axios.create({
// API 请求的默认前缀
baseURL: process.env.VUE_APP_PREVIEW === 'true' ? '/api' : process.env.VUE_APP_API_BASE_URL,
timeout: 30000 // 请求超时时间
})
// request interceptor
request.interceptors.request.use(config => {
const token = storage.get(ACCESS_TOKEN)
// 如果 token 存在
// 让每个请求携带自定义 token 请根据实际情况自行修改
if (token) {
config.headers['Authorization'] = token
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
})
// response interceptor
request.interceptors.response.use(
response => {
// return response.data //可以不做任何处理,在这里了直接返回请求会的结果
const res = response.data || {}
if (!res.success) {
// 401: Unauthorized
if (res.code === 401) {
notification.error({
key: 'Unauthorized',
message: '错误',
description: '身份验证失败,请重新登录!'
})
// 从 localstorage 获取 token
const token = storage.get(ACCESS_TOKEN)
if (token) {
store.dispatch('Logout').then(() => {
window.location.reload()
})
}
}
return Promise.reject(response.data)
} else {
return res
}
},
error => {
return Promise.reject(error)
}
)
export default {
/**
*
* @param {String} url
* @param {Object} data
* @param {String} isForm
* @param {Object} config
*
* 这里是通用请求
* 如果需要特殊的配置在config中配置
*
*/
post (url, data, isForm, config = {}) {
if (isForm === 'FORM') {
const formHeaders = {
// 'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
}
const transformRequest = data =>
qs.stringify(data, {
encode: false,
allowDots: true,
arrayFormat: 'indices'
})
config.transformRequest = config.transformRequest ? [transformRequest, ...config.transformRequest] : [transformRequest]
config = { headers: formHeaders, ...config }
}
// 文件上传
if (isForm === 'FILE') {
const formHeaders = {
'Content-Type': 'multipart/form-data'
}
config = { headers: formHeaders, ...config }
const forms = new FormData()
forms.append('file', data)
data = forms
}
return request.post(url, data, config)
//return request.post(url, data, config).then(res => res).catch(e => e),这里的处理和上边的不同是因为上面没做处理的结果return出来的promise对象,做了处理就return出来的是一个经过处理的对象,
},
/**
*
* @param {String} url
* @param {Object} params
*/
get (url, params, config) {
return request.get(url, { params: params }, config)
//retrun request.get(url, { params: params }, config)//同上
}
}
复制代码
难点
-
这就是一个正常的封装request请求的过程,足以应对日常的前端开发任务,上述中之所以return request可以经过.then().catch()处理,也可以不经过,这么做的原因是为了应对下面的两种场景,一种是用async await来调用接口,一种是用接口名().then().catch()来调用接口
-
如果你喜欢用async await来请求接口,那么你就用后者,如果你喜欢用接口名().then().catch()来请求接口那你就用前者。
-
当然,如果你用后者封装return request也可以用接口名().then().catch()形式来调用接口,但是这时候不论后端返回的结果是成功还是失败都会进入到.then()中,而不会到.catch(),但切记如果你用了return request.post(url, data, config),那你再使用async await就会出错,因为此时return的的一个promise对象,可能是个异常,而async await中没有catch操作,但如果你非要这样用也不是不行,记得在使用async await的时候加上try…catch…
async updateStatus () {
//当request封装的时候没用.then().catch()处理,想用async await 就这样写
try {
const data = await updateSysOrgOperatorsStatus()
this.$message.success(data.data.message)
} catch (error) {
this.$message.error(error.message)
}
//reques封装的时候用了.then().catch(),async await就可以如下这样正常使用
const data = await updateSysOrgOperatorsStatus()
if (data.success) {
this.$message.success(data.data.message)
} else {
this.$message.error(data.message)
}
//reques封装的时候不加.then().catch()就可以如下这样正常使用
updateSysOrgOperatorsStatus().then(res => {
this.$message.success(res.message)
}).catch(err => {
this.$message.error(err.message)
})
},
复制代码
总结
我个人比较建议用 return request.post(url, data, config),也就是前者,这样看起来简单,用起来也方便,但听一个大佬说还是用后者比较好