手写简易发布订阅
实现思路为先定义一个事件池,每当订阅一个方法,就会查看事件池内有没有相应事件的对象,没有则创建,有则追加。触发事件时,则会执行相应事件对象下的所有回调函数。
vue的$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
| class EventEmitter { constructor() { this.events = {}; } on(eventName,callback) { if (!this.events[eventName]) { this.events[eventName] = [callback] } else { this.events[eventName].push(callback) } } emit(eventName) { this.events[eventName] && this.events[eventName].forEach(cb => cb()); } removeListener(eventName, callback) { if (this.events[eventName]) { this.events[eventName] = this.events[eventName].filter(cb => cb != callback) } } once(eventName,callback) { let fn = () => { callback(); this.removeListener(eventName,fn); } this.on(eventName,fn) } }
|
使用方式
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
| let em = new EventEmitter(); let workday = 0; em.on("work", function() { workday++; console.log("work everyday"); });
em.once("love", function() { console.log("just love you"); });
function makeMoney() { console.log("make one million money"); } em.on("money",makeMoney);
let time = setInterval(() => { em.emit("work"); em.removeListener("money",makeMoney); em.emit("money"); em.emit("love"); if (workday === 5) { console.log("have a rest") clearInterval(time); } }, 1);
|
1 2 3 4 5 6 7
| work everyday just love you work everyday work everyday work everyday work everyday have a rest
|