• 发布订阅模式 simple


    /*
     * @Author: pengLei
     * @LastEditors: pengLei
     * @Date: 2021-12-14 14:08:01
     * @LastEditTime: 2021-12-14 16:09:03
     * @motto: Still water run deep
     * @Description: 发布者
     * @FilePath: \鱼泡PC网\src\dep\publish.ts
     */
    // ! 重要方法,不容删除
    
    /** 发布者 */
    class Publish {
      name: string
      id: number
      messageMap: { [key: string]: {id: number; name: string; [x: string]: any}[] }
      /** name等同于给当前发布者一个名称 */
      constructor(name: string) {
        /** 消息事件订阅者集合对象 */
        this.messageMap = {}
        /** 随机id模拟唯一 */
        this.id = Date.now() + Math.ceil(Math.random() * 10000)
        this.name = name
      }
    
      /** 添加消息订阅者(subscriber等于订阅者) */
      addListener(subscriber: any, message: string) {
        if (!subscriber || !message) return false
        /** 如果消息列表不存在,就新建 */
        if (!this.messageMap[message]) {
          this.messageMap[message] = []
        }
        /** 比对ID查询!!! */
        const existIndex = this.messageMap[message].findIndex(exitSubscriber => exitSubscriber.id === subscriber.id)
        /** 不存在这个订阅者时添加 */
        if (existIndex === -1) {
          /** 吧订阅者装进去 */
          this.messageMap[message].push(subscriber)
        } else {
          /** 存在的时候呢 直接替换 */
          this.messageMap[message][existIndex] = subscriber
        }
      }
    
      /** 删除消息订阅者 */
      removeListener(subscriber: any, message: string) {
        if (!subscriber) return false
    
        /** 如果传了message只删除此message下的订阅关系,否则删除此订阅者的所有订阅关系 */
        const messages = message ? [message] : Object.keys(this.messageMap)
        /** 遍历Key */
        messages.forEach(_message => {
          const subscribers = this.messageMap[_message]
          if (!subscribers) return false
    
          let i = subscribers.length
          while (i--) {
            if (subscribers[i].id === subscriber.id) {
              subscribers.splice(i, 1)
            }
          }
          /** 数组元素如果没有了。直接吧订阅器删除 */
          if (!subscribers.length) delete this.messageMap[_message]
        })
      }
      
      /** 发布通知 */
      publish<D extends any>(message: string, info: D) {
        const subscribers = this.messageMap[message] || []
        let handlerKey = message + "_" + this.id + "_handler"
        /** 找出当前索引订阅者,依次发送通知 */
        subscribers.forEach(subscriber => {
          subscriber[handlerKey](subscriber, info)
        })
        return this
      }
    }
    
    export default Publish
    /*
     * @Author: pengLei
     * @LastEditors: pengLei
     * @Date: 2021-12-14 14:03:52
     * @LastEditTime: 2021-12-14 16:08:15
     * @motto: Still water run deep
     * @Description: 订阅者
     * @FilePath: \鱼泡PC网\src\dep\subscribe.ts
     */
    // ! 重要方法,不容删除
    
    type listenType = {
      publisher: any,
      message: string,
      handler: (subscribe: {[x: string]: any}, info: any) => void
    }
    
    /** 订阅者 */
    class Subscribe {
      id: number;
      name: string;
      [x: string]: any
      /** name等同于给当前订阅者一个名称 */
      constructor(name: string = 'subscriber') {
        this.name = name
        /** 随机id模拟唯一 */
        this.id = Date.now() + Math.ceil(Math.random() * 10000)
      }
      /** 
       *  订阅器
       *  @publisher 订阅的是哪个发布者(比如你订阅的是鱼泡发布者)
       *  @message 订阅的消息,(非常重要的字段)(比如你订阅的是鱼泡发的招工信息key。绑定关系)
       *  @handler 收到消息后的处理方法
       */
      listen({publisher, message, handler}: listenType) {
        /** 订阅消息的回调函数 */
        if (publisher) {
          /** 一个订阅者可以同时订阅多个发布者,所以回调函数要拼接上对应发布者的id */
          this[message + '_' + publisher.id + "_handler"] = handler
          publisher.addListener(this, message)
        }
        /** 链式 */
        return this
      }
      /** 取消订阅 */
      unlisten(publisher: any, message: string) {
        if (publisher) {
          publisher.removeListener(this, message)
        }
        /** 链式 */
        return this
      }
    }
    
    export default Subscribe

    /*
     * @Author: pengLei
     * @LastEditors: pengLei
     * @Date: 2021-12-14 15:34:28
     * @LastEditTime: 2021-12-14 16:06:22
     * @motto: Still water run deep
     * @Description: 订阅器(采集所有需要订阅的实例)
     * @FilePath: \鱼泡PC网\src\dep\listener.ts
     */
    import {Subscribe, Publish} from "."
    
    /** 示例 (可以链式,多绑定)说白了就是一个人可以绑定A的发布者,也可以绑定B的发布者,还可以绑定A的发布其他信息
     *  LoginSubscribe.listen({
            publisher: APublish, // 绑定发布者是A
            message: '找活', // 绑定发布者是发布的找活
            handler: (self, info) => {
              console.log(self, dispatch)
            }
          }).listen({
            publisher: BPublish,
            message: '招工',
            handler: (self, info) => {
              consol.log(info == '我要找一个工人啦')
              console.log(self, dispatch)
            }
          })
        
        BPublish.publish('招工', '我要找一个工人啦!')
    
        如不多个人绑定了B的招工,那么B发布者一旦放送信息,全体订阅者会收到信息
     */
    
    /** 登录的发布者 */
    const LoginPublish = new Publish('LoginPublish')
    /** 登录的订阅者 */
    const LoginSubscribe = new Subscribe('LoginSubscribe')
    
    /** 你可以在这里处理更多的发布订阅 */
    // ....
    
    export {
      LoginPublish,
      LoginSubscribe
    }
  • 相关阅读:
    系统学习前端
    电脑上的图标拖不动
    js 给 input的value赋值
    js forEach的坑
    h5兼容性问题总结
    行内元素与块级元素
    百度搜索指令
    微信h5监听页面显示隐藏
    跨浏览器事件处理函数
    鼠标事件分析(onmouseenter、onmouseover、onmouseleave和onmouoseout的区别)
  • 原文地址:https://www.cnblogs.com/plBlog/p/15688470.html
Copyright © 2020-2023  润新知