发布订阅模式是一种设计模式,应用广泛,例如DOM2的addEventListener、Vue2的eventBus
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
| const cb = ()=> { console.log('触发了') }
document.addEventListener('myevent', cb, { once: false } )
const myEvent = new Event('myevent')
let count = 1 let timer = null timer = setInterval(() => { if(count > 5) { clearInterval(timer) document.removeEventListener(myEvent, cb) } else { document.dispatchEvent(myEvent) } count++ }, 1000)
|
手写实现一个发布订阅模式:
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 65 66
| interface EmitterImpl { events: Map<string, Set<Function>> once: (name: string, cb: Function)=>void on: (name: string, cb: Function)=>void emit: (name: string, ...args: any[])=>void off: (name: string, cb: Function)=>void }
class Emitter implements EmitterImpl { events: Map<string, Set<Function>> constructor() { this.events = new Map() }
once(name: string, cb: Function) { const callback = (...args: any[])=> { cb(...args) this.off(name, callback) } this.on(name, callback) }
on(name: string, cb: Function) { if(this.events.has(name)) { this.events.get(name)?.add(cb) } else { this.events.set(name, new Set([cb])) } }
emit(name: string, ...args: any[]) { let set = this.events.get(name) if(set) { set.forEach(cb=> { cb(...args) }) } }
off(name: string, cb: Function) { let set = this.events.get(name) if(set) { set.delete(cb) } } }
const bus = new Emitter()
const cb = (b: boolean, n1: number, n2: number, s: string)=> { console.log('触发了', b, n1, n2, s) }
bus.on('msg', cb) bus.on('msg', ()=> {console.log('12321')}) bus.once('msg', ()=> {console.log('once')})
let count = 0 setInterval(()=> { if(count > 2) { bus.off('msg', cb) } bus.emit('msg', true, 114, 514, 'yajue') count++ }, 1000)
|