EventHub 是一种事件发布-订阅模式的实现。
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
实现
- 每个实例有一个调度中心。负责存储消息与订阅者的对应关系,有消息触发时,负责通知订阅者。
- on方法订阅的事件注册(Subscribe)到调度中心。
- once方法只订阅一次,执行后移除订阅事件。
- off方法从调度中心移除订阅的事件。
- emit方法发布事件,并通过调度中心通知所有的订阅者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| class EventHub { constructor() { this.channel = {} }
on(name, fn) { this.channel[name] = this.channel[name] || [] this.channel[name].push(fn) }
off(name, fn) { const list = this.channel[name] || [] const index = list.indexOf(fn) if(index < 0) return list.splice(index, 1) }
once(name, fn) { this.channel[name] = this.channel[name] || [] let one = (arg) => { fn.call(null, arg) } one.fn = fn one.off = () => { this.off(name, one) } this.on(name, one) }
emit(name, data) { let list = this.channel[name] || [] let ones = [] list.forEach(fn => { fn.call(null, data) fn.off && ones.push(fn) }) ones.forEach(fn => fn.off()) } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let q = new EventHub()
q.on('click', function(data) { console.log('on') })
q.once('click', function() { console.log('once') })
q.emit('click') q.emit('click')
|
demo
demo地址