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

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

举个栗子✏️

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

总结❤️

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

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

相关推荐
牧羊狼的狼1 小时前
React 中的 HOC 和 Hooks
前端·javascript·react.js·hooks·高阶组件·hoc
知识分享小能手2 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
luckys.one2 小时前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
魔云连洲2 小时前
深入解析:Vue与React的异步批处理更新机制
前端·vue.js·react.js
mCell3 小时前
JavaScript 的多线程能力:Worker
前端·javascript·浏览器
weixin_437830944 小时前
使用冰狐智能辅助实现图形列表自动点击:OCR与HID技术详解
开发语言·javascript·ocr
超级无敌攻城狮4 小时前
3 分钟学会!波浪文字动画超详细教程,从 0 到 1 实现「思考中 / 加载中」高级效果
前端
excel5 小时前
用 TensorFlow.js Node 实现猫图像识别(教学版逐步分解)
前端
gnip6 小时前
JavaScript事件流
前端·javascript
小菜全6 小时前
基于若依框架Vue+TS导出PDF文件的方法
javascript·vue.js·前端框架·json