好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用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  }

 

查看更多关于使用typescript 写一个简单的事件监听/发布订阅模式的类的详细内容...

  阅读:86次