[toc]
推导链
Q1: 发布订阅是什么? → 事件中心:on 订阅、emit 发布、off 取消 → 发布者和订阅者不直接通信,通过事件中心
Q2: 观察者模式区别? → 观察者直接订阅目标,目标直接通知观察者 → 没有中间的事件中心
Q3: 核心数据结构? → 发布订阅:{ eventName: [cb1, cb2] } → 观察者:observers: [observer1, observer2]
发布订阅模式
javascript
class EventEmitter {
constructor() {
// 调度中心
this.events = {};
}
// 1. 订阅事件
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
// 2. 发布事件
emit(eventName, ...args) {
const callbacks = this.events[eventName];
if (callbacks) {
callbacks.forEach(cb => cb.apply(this, args));
}
}
// 3. 取消订阅
off(eventName, callback) {
const callbacks = this.events[eventName];
if (callbacks) {
this.events[eventName] = callbacks.filter(cb => cb !== callback);
}
}
// 4. 只执行一次
once(eventName, callback) {
const oneTimeFn = (...args) => {
callback.apply(this, args);
this.off(eventName, oneTimeFn);
};
this.on(eventName, oneTimeFn);
}
}
// 测试
const bus = new EventEmitter();
// 订阅消息
const handleMsg = (data) => console.log('收到消息:', data);
bus.on('message', handleMsg);
// 发布消息
bus.emit('message', 'Hello World!'); // 打印: 收到消息: Hello World!
// 取消订阅后再次发布
bus.off('message', handleMsg);
bus.emit('message', '听得到了吗?'); // 无输出观察者模式
javascript
// 被观察者 (Subject)
class Subject {
constructor() {
this.observers = []; // 存储所有观察者
}
// 添加观察者
add(observer) {
this.observers.push(observer);
}
remove(observer) {
this.observers = this.observers.filter(o => o !== observer)
}
// 通知所有观察者
notify(message) {
this.observers.forEach(observer => {
observer.update(message);
});
}
}
// 观察者 (Observer)
class Observer {
constructor(name) {
this.name = name;
}
// 更新方法,被 Subject 调用
update(message) {
console.log(`${this.name} 收到消息: ${message}`);
}
}
// 创建被观察者
const subject = new Subject();
// 创建观察者
const obs1 = new Observer("A");
const obs2 = new Observer("B");
subject.add(obs1);
subject.add(obs2);
// 被观察者发布消息
subject.notify("hello world!");