• 使用typescript 写一个简单的事件监听/发布订阅模式的类


    我们需要弄清楚,观察者模式和发布订阅模式是不一样的,一张图理解:

    两者区别:

      1. 观察者 模式只有观察者和被观察者两者,是松耦合

      2. 发布订阅模式除了发布者和订阅者外,还有一个调度中心,是解耦的,两者没有直接关系

      3. 观察者主要是同步方式实现,二发布订阅模式多数是异步实现,比如消息队列

    用typescript 简单实现一个发布订阅模式的类

     1 class byEvent {
     2     Events: { [key: string]: Array<Function> } //约束示例:{"eventName":[function(){},function(){},.....],......}
     3     constructor() {
     4         this.Events = {}
     5     }
     6     /**
     7      * 发布/ 触发
     8      * @param eventName 
     9      * @param args 
    10      */
    11     emit(eventName: string, ...args: any) {
    12         let callbackList = this.Events[eventName] || [];
    13         callbackList.forEach(fn => fn.apply(this, args))
    14         return this;
    15         // 如果用js写,遍历的时候要做一下判断是否是函数,ts 用类型约束,在调用或者编译阶段会检测是否合法
    16         // callbackList.map(fn=>{
    17         //     if(typeof fn==="function") fn.apply(this,args)
    18         // })
    19     }
    20     /**
    21      * 订阅/监听
    22      * @param eventName 
    23      * @param callback 
    24      */
    25     on(eventName: string, callback?: Function) {
    26         // if(!eventName||typeof eventName !=="string") return  ;// 因为用了ts 写,所以这句不用写了,如果是js写,建议加这判断
    27         let callbackList = this.Events[eventName] || [];
    28         callback && callbackList.push(callback)
    29         this.Events[eventName] = callbackList
    30         return this;
    31 
    32     }
    33     /**
    34      * 只订阅一次/监听一次:
    35      * 思路:
    36      * 1. 重新包装一个回调函数(有名的),进行注册订阅/监听,
    37      * 2. 包装函数里面直接调用 once方法的第二个参数回调函数,然后调用off方法 卸载该包装函数
    38      * @param eventName 
    39      * @param callback 
    40      */
    41     once(eventName: string, callback?: Function) {
    42         // if(!eventName||typeof eventName !=="string") return ;
    43         let decor = (...args: any[]) => {
    44             callback && callback.apply(this, args)
    45             this.off(eventName, decor)
    46         }
    47         this.on(eventName, decor)
    48         return this;
    49 
    50     }
    51     /**
    52      * 卸载/取消 某一个回调监听(不是取消eventName的所有回调监听),主要配合once一起,实例单独调用,无意义
    53      * @param eventName 
    54      * @param callback 
    55      */
    56     off(eventName: string, callback: Function) {
    57         let callbackList = this.Events[eventName] || [];
    58         let resCallbacks = callbackList.filter(fn => fn !== callback)
    59         this.Events[eventName] = resCallbacks
    60         return this;
    61 
    62     }
    63     /**
    64      * 卸载/取消 指定eventName 的所有订阅/监听
    65      * @param eventName 
    66      * @param callback 
    67      */
    68     remove(eventName: string, callback?: Function) {
    69         this.Events[eventName] = [];
    70         callback && callback()
    71         return this;
    72 
    73     }
    74 
    75 }
    76 
    77 // 使用示例
    78 let o = new byEvent()
    79 setInterval(() => {
    80     o.emit("name", 123)
    81     o.emit("name", 10, 20)
    82     o.emit("post", { name: 1212 }, "post")
    83 
    84 }, 1000);
    85 setTimeout(() => {
    86     o.remove("name", function () {
    87         console.log("remove")
    88     })
    89 }, 3000)
    90 o.once("name", function (...res: any[]) {
    91     console.log("once-name1", res)
    92 })
    93 o.on("name", function (...res: any[]) {
    94     console.log("on-name2", res)
    95 })
    96 o.on("post", function (...res: any[]) {
    97     console.log("on-post", res)
    98 }
  • 相关阅读:
    EF架构~Dapper.Contrib不能将Linq翻译好发到数据库,所以请不要用它
    docker~aspnetcore2.0镜像缺少libgdiplus问题
    DotNetCore跨平台~Quartz定时单次任务
    Java学习笔记——JDBC之与数据库MySQL的连接以及增删改查等操作
    可爱的玩笑
    树蛙和摄影师
    axis WebServices 完美调用天气预报,查询、显示 代码!
    跟随一生的帐号密码
    [置顶] VB6基本数据库应用(三):连接数据库与SQL语句的Select语句初步
    Citrix 服务器虚拟化之九 Xenserver虚拟机的XenMotion
  • 原文地址:https://www.cnblogs.com/beyonds/p/13590773.html
Copyright © 2020-2023  润新知