发布订阅模式
/** 发布者 */ 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
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 订阅的是哪个发布者(比如你订阅的是xxx) * @message 订阅的消息,(非常重要的字段)(比如你订阅的是xx发的招工信息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
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 }