前后端联调的规范(初级)
程序员文章站
2022-06-03 21:27:20
...
-
后端返回的状态
(1) -404/-500/-201/-403 等错误
(2) 网络/超时 等错误
(3) 返回 因为参数类型或者必传参数没传 等常规性错误 -
一般错误处理
在axios的封装函数中拦截
axios.interceptors.response.use(res => {
// p2常规性错误捕获
}, err => {
// p1错误捕获
// err.response.status
// 200 成功
// 300 重定向
// 400 请求错误
// 500 服务器错误
})
如何更好的对axios进行拦截处理
axios拦截的作用
-
设定默认的url前辍
-
设定header请求头参数
-
添加token以及公共参数
-
对错误处理进行拦截
-
默认url前辍
axios.defaults.baseURL = process.env.VUE_APP_BASE_URL
其中VUE_APP_BASE_URL参数配合package.json配置环境
- 设置header请求头参数
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
- 添加token以及公共参数
axios.interceptors.request.use(config => {
if (window.localStorage.getItem('token')){
config.headers.common['Authorization'] = window.localStorage.getItem('token');
}
})
- 对错误处理进行拦截
axios.interceptors.response.use(res => {
if(res.status === 201) {
...
}
return Promise.resolve(res.data);
}, err => {
if (error.response && error.response.status >= 500){
...
}
return Promise.resolve(res.data);
})
完整代码
import axios from 'axios'
import Router from '@/router/index'
// 封装的本地存储类
class Db {
constructor(status = 1, scope = 'anlin') {
if (typeof status !== 'number' || typeof scope !== 'string') {
alert('传入的参数格式不正确,将使用默认的参数配置')
this.scope = 'anlin'
this.status = 1
} else {
this.scope = scope
this.status = status
}
}
setItem (key, value, item) {
item.setItem(this.scope + '_' + key, JSON.stringify(value))
}
set (key, value) {
if (this.status === 1) {
this.setItem(key, value, localStorage)
} else {
this.setItem(key, value, sessionStorage)
}
}
getItem (key, item) {
try {
return JSON.parse(item.getItem(this.scope + '_' + key))
} catch {
return null
}
}
get (key) {
if (this.status === 1) {
return this.getItem(key, localStorage)
} else {
return this.getItem(key, sessionStorage)
}
}
clearItem (item) {
for (const key in item) {
if (key.indexOf(this.scope) !== -1) {
item.removeItem(key)
}
}
}
clear () {
if (this.status === 1) {
this.clearItem(localStorage)
} else {
this.clearItem(sessionStorage)
}
}
removeItem (key, item) {
item.removeItem(this.scope + '_' + key)
}
remove (key) {
if (this.status === 1) {
this.removeItem(key, localStorage)
} else {
this.removeItem(key, sessionStorage)
}
}
}
const loc = new Db()
// 模拟浏览器的缓存数据,用来测试
loc.set('id', '1')
loc.set('token', 'abcdefg')
// 判断传入的数据类型
const verType = data => {
const dataType = Object.prototype.toString.call(data)
return dataType.split(" ")[1].replace(']', '')
}
// 设定axios初始化
axios.defaults.baseURL = process.env.VUE_APP_BASE_URL
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
// 导出函数,当调用函数的时候,设定axios的拦截器并返回axios
export default () => {
// 发起请求的时候拦截
axios.interceptors.request.use(config => {
const {data, headers} = config
// 如果存在token,则在请求头带上参数
const token = loc.get('token')
token && (headers.common['Authorization'] = token)
// 如果config包含data
if (data){
// 则增加公共参数
const id = loc.get('id')
id && (data.id = id)
// 如果config.data存在undefined,则把对应的属性删除
if (verType(data) === 'Object'){
const keyArr= Object.keys(data)
for(let i of keyArr) {
if(data[i] === undefined) {
delete data[i]
}
}
}
}
return config;
}, err => {
return Promise.reject(err);
})
axios.interceptors.response.use(res => {
// 如果后端返回的状态为201, 表示权限不够
if (res.status === 201){
// 清空浏览器缓存数据,并跳转到首页(登陆页)
loc.clear()
Router.push('/')
}
return Promise.resolve(res.data);
}, err => {
const response = err.response
if (response && response.status >= 500) {
alert('服务器错误')
}
if (response && response.status === 404) {
alert('接口不存在')
}
return Promise.reject(err);
});
return axios;
}
- 避免出现服务器错误
后端验证 - 参数 -> 类型和必有字段验证
// 传入一个数组,数组中对象进行undefined和类型的判断
const checkUndefined = (arr) => {
let flog = true;
for (let i of arr) {
if (i[i.label] === undefined) {
flog = false
break;
} else {
if (typeof i[i.label] !== i.type) {
flog = false
break;
}
}
}
return flog;
}
router.post('/note', async ctx => {
const { user, title, content } = ctx.request.body;
const verFlog = checkUndefined([
{user: user,type: 'string',label: 'user'},
{title: title,type: 'string',label: 'title'},
{content: content,type: 'string',label: 'content'},
]);
if (verFlog) {...} else {...}
})
- 超时处理 -> 返回对应的数据
ctx.body = await Note.find(findObj).limit(skip).skip(skip - limit).then(async res => {
let length = await Note.find({ user }).count()
return {
code: 0,
msg: '查询成功',
data: res,
total: length
}
}).catch(err => {
// 疑问1: 如果await.find... 的处理超时,这里会被捕获吗? 如果会,超时的时间是多久?
// 如果这里不能捕获超时的话,需要使用定时器来处理
return util.back(500)
})
- 代码错误 -> 异常捕获 -> 返回对应的数据
ctx.body = await Note.find(findObj).limit(skip).skip(skip - limit).then(async res => {
let length
try{
let length = await Note.find({ user }).count()
}catch{
let length = 0
}
return {
code: 0,
msg: '查询成功',
data: res,
total: length
}
}).catch(err => {
return util.back(500)
})
上一篇: 设置堆内存大小