事件触发器EventEmitter
发布订阅模式:
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 42 43 44 45 46 47 48 49
| class EventEmitter { constructor() { this._event = [] }
on(eventName, fn) { let callback = this._event[eventName] || []; callback.push(fn); this._event[eventName] = callback; return this; }
emit(...args) { let eventName = args[0]; let params = args.slice(1); let event = this._event[eventName]; event.forEach(fn => fn.apply(this, params)); return this; }
off(eventName, fn) { let callback = this._event[eventName]; this._event[eventName] = callback && callback.filter(_fn => _fn !== fn); return this; }
once(eventName, fn) { let wrapFun = function(...args) { fn.apply(this, args); this.off(eventName, wrapFun); } this.on(eventName, wrapFun); return this; } }
let event = new EventEmitter(); function handleClick(num) { console.log('--click--', num); } function handleClick1(num) { console.log('--click1--', num); } event.on('click', handleClick); event.on('click', handleClick1);
... event.emit('click', 10); event.emit('click', 100);
|
上面的eventEmitter类的实现就是基于发布订阅模式。在阮一峰老师的《Javascript异步编程的4种方法》中提到:
我们假定,存在一个”信号中心”,某个任务执行完成,就向信号中心”发布”(publish)一个信号,其他任务可以向信号中心”订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做”发布/订阅模式”(publish-subscribe pattern),又称”观察者模式”(observer pattern)。
发布订阅模式可以理解为是观察者模式的一种变形,两者的区别是:发布/订阅模式在观察者模式的基础上,在目标和观察者之间增加一个调度中心。

观察者模式(有待考证):
应该用Object.defineProperty() 或者用 Proxy 来实现。下面代码有点问题。待修改
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| class Observe { constructor() { this.dep = []; }
watcher(propertyName, fn) { let handle = this.dep[propertyName] || []; handle.push(fn); this.dep[propertyName] = handle; return this; }
unwatch(propertyName) { let depen = this.dep[propertyName]; depen = depen && []; this.dep[propertyName] = depen; return this; }
notify(propertyName, ...args) { let handle = this.dep[propertyName]; if (handle && handle.length > 0) { handle.forEach(fn => fn.apply(this, args)); } return this; } }
let observe = new Observe();
let obj = { a: 'first', b: 'second' }
let handle = { get(target, property) { return Reflect.get(target, property); }, set(target, key, value) { observe.notify(key); Reflect.set(target, key, value); } }
function watcher1() { console.log('watchee1: a have chage'); }
function watcher2() { console.log('watchee2: a have chage'); }
observe.watcher('a', watcher1); observe.watcher('a', watcher2);
let proxy = new Proxy(obj, handle);
proxy.a = 10; proxy.a = 130;
observe.unwatch('a');
proxy.a = 100;
|