今天给大家搬运的是利用发布-订阅模式对代码进行解耦

你是否在项目封装的通用代码里这么干过,或者公司目前的代码就是这么做的呢?

举个栗子✏️

公司里的中后台项目封装的通用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({
  ...
  })
})
...

总结❤️

✅通过这样就能使用发布-订阅模式对业务代码逻辑进行充分解耦拉,也可以在你觉得很臃肿的很多其他业务代码里使用。

✅这样不仅仅又多掌握并运用了一种设计模式在今后吹嘘项目时也可以说自己的项目引入了发布订阅的模式进行代码解耦

相关推荐
攀登的牵牛花3 分钟前
前端向架构突围系列 - 框架设计(七):反应式编程框架Flower的设计
前端·架构
佛系打工仔6 分钟前
K线绘制前言
前端
遇见~未来30 分钟前
JavaScript数组全解析:从本质到高级技巧
开发语言·前端·javascript
哈__31 分钟前
基础入门 React Native 鸿蒙跨平台开发:TabBar 底部导航栏
javascript·react native·react.js
lili-felicity32 分钟前
React Native 鸿蒙跨平台开发:Animated 实现鸿蒙端组件的左右滑动动画
javascript·react native·react.js
石像鬼₧魂石34 分钟前
80 端口(Web 服务)渗透测试完整总结(含踩坑 + 绕过 + 实战流程)
linux·运维·服务器·前端·网络·阿里云
哈__42 分钟前
React Native 鸿蒙跨平台开发:StatusBar 状态栏组件
javascript·react native·react.js
C_心欲无痕1 小时前
nginx - 核心概念
运维·前端·nginx
开开心心_Every1 小时前
安卓做菜APP:家常菜谱详细步骤无广简洁
服务器·前端·python·学习·edge·django·powerpoint
前端_Danny1 小时前
用 ECharts markLine 实现节假日标注
前端·信息可视化·echarts