你是否在项目封装的通用代码里这么干过,或者公司目前的代码就是这么做的呢?
举个栗子✏️
公司里的中后台项目封装的通用http库里请求
与响应
拦截器是不是类似大概这样写的?
特别是如果在后端的
响应码
很多需要分开写逻辑时
js
...
import router from '@/router'
import {Modal,message} from 'ant-design-vue'
export class Request {
instance: AxiosInstance;
baseConfig: AxiosRequestConfig = {
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 100000 * 60 * 3 * 100,
};
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(Object.assign(this.baseConfig, config));
this.instance.interceptors.request.use(
(_config: AxiosRequestConfig) => {
...
return _config;
},
(error: AxiosError) => Promise.reject(error)
);
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
return response;
},
async (error: any) => {
const data = error?.response?.data
if (data && data.code === 60009) {
...
Modal.error(...)
}
if (data && data.code === 60010) {
...
message.warn(...)
}
if (error.response.status === 401) {
router.push('/login')
}
...
return Promise.reject(error.response);
}
);
}
这样的话一个网络请求库耦合的东西就太多而显得臃肿。
我们想一个网络请求库它就只需要做网络请求相关的工作就行了,没必要一会儿又需要引入UI组件弹窗显示,一会儿又要引入路由的方法进行跳转
像这样✨
1️⃣ 假如401需要跳转登录页面,触发一个需要路由去处理的事件,然后路由模块自己去接收处理
2️⃣ 假如60009需要UI组件message发出一个警告的提示就触发一个需要UI弹窗组件需要处理的事件,自己去处理
3️⃣ 假如600010需要UI组件Modal发出弹窗确认,触发一个事件,UI组件相应自己去接收处理
......
js
async (error: any) => {
const data = error?.response?.data
if (data && data.code === 60009) {
emit()
}
if (data && data.code === 60010) {
EventEmitter.emit('UI:OPEN_MESSAGE',...)
}
if (axios.isCancel(error)) return
if (error.response.status === 401) {
EventEmitter.emit('API:UN_AUTH')
}
if (data && (data.code ===1||data.code===50002)) {
EventEmitter.emit('UI:OPEN_MESSAGE',...)
}
if (data && data.code !== 60009&&data.code !== 60010) {
EventEmitter.emit('UI:OPEN_MODAL',...)
}
。。。
return Promise.reject(error.response)
}
EventEmitter⭐
js
const eventNames = ["API:UN_AUTH", "API:INVALID_TOKEN","UI:OPEN_MESSAGE","UI:OPEN_MODAL" ,"..."] as const;
type EventName = (typeof eventNames)[number];
class EventEmitter {
private listeners: Record<EventName, Set<Function>> = {
"API:UN_AUTH": new Set(),
"API:INVALID_TOKEN": new Set(),
};
on(eventNames: EventName, listener: Function) {
this.listeners[eventNames].add(listener);
}
emit(eventNames: EventName, ...args: any[]) {
this.listeners[eventNames].forEach((cb) => cb(...args));
}
}
export default new EventEmitter();
导出一个全局的EventEmitter,在需要触发和需要订阅的模块引入使用
router
js
import eventEmitter from '@utils/EventEmitter'
...
eventEmitter.on('API:UN_AUTH',()=>{
router.push('/login')
})
...
uiUtils
js
import eventEmitter from '@utils/EventEmitter'
import {message,Modal} from 'ant-design-vue'
...
eventEmitter.on('UI:OPEN_MESSAGE',(...args)=>{
message.wran({
...
})
})
eventEmitter.on('UI:OPEN_MODAL',(...args)=>{
Modal.wran({
...
})
})
...