前端中的设计模式——发布订阅模式
在前端中观察者通常抽象为事件更具实用性,但这种模式会有一个问题.
假设想在登陆成功后通知组件A、B、C更新view(A、B、C未登录时view处于缺省状态).
- 用观察者模式的话 const ob = new Observable() // A、B、C进行一波订阅 ob.add(update1, () => { console.log(login successful!) }) ob.add(update2, () => { console.log(login successful!) }) ob.add(update3, () => { console.log(login successful!) }) // 通知A、B、C ob.notify(update1) ob.notify(update2) ob.notify(update3) 可以看出,登陆成功后想通知组件A、B、C更新view.前提得三个组件都进行订阅,并发布三次通知,才能实现.
- 希望的做法(猜想模式): const ob = new Observable() const update = new Type() // 组件a update.add(() => { console.log(login successful 1!) }) // 组件b update.add(() => { console.log(login successful 2!) }) // 组件c update.add(() => { console.log(login successful 3!) }) ob.add(update) ob.notify(update)
- 区别:
- 发布订阅模式的引入 理解: 淘宝模式的抽象化 图解 实现: // 事件总线(调度中心) class EventBus { constructor() { this.subscribers = []; } $on(fn) { this.subscribers.push(fn); } $off(fn) { this.subscribers.forEach((_fn, index) => { fn === _fn && this.subscribers.splice(index, 1); }) } $once(fn) { fn.once = true; this.subscribers.push(fn); } $notify(params) { this.subscribers.forEach(fn => { fn(params); fn.once && this.$off(fn); }); } } // 发布 class Pub { constructor() { this.events = []; } $increase(event) { this.events.push(event); } $broadcast(event, ...params) { this.events.forEach(_event => { event === _event && _event.$notify(...params); }) } } module.exports = { Pub: new Pub(), EventBus }; 使用 const ev1 = new EventBus(); const ev2 = new EventBus(); // 订阅主题 ev1.$on(data => { console.log(`${ data}==>订阅者1收到消息了`); }); ev1.$on(data => { console.log(`${ data}==>订阅者2收到消息了`); }); ev2.$on(data => { console.log(`${ data}==>订阅者2收到消息了`); }); ev2.$once(data => { console.log(`${ data}==>订阅者3收到消息了`); }); // 加入主题 Pub.$increase(ev1); Pub.$increase(ev2); // 发布主题 Pub.$broadcast(ev1, 主题1更新了~); Pub.$broadcast(ev2, 主题2更新了~); Pub.$broadcast(ev2, 主题2再次更新了~); /* 主题1更新了~==>订阅者1收到消息了 主题1更新了~==>订阅者2收到消息了 主题2更新了~==>订阅者2收到消息了 主题2更新了~==>订阅者3收到消息了 主题2再次更新了~==>订阅者2收到消息了 */
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
记账系统项目开发(一):需求分析