nicenote/docs/fea/pattern/eventEmitter.md
2021-08-25 20:10:25 +08:00

98 lines
2.1 KiB
Markdown

---
nav:
title: 前端
path: /fea
group:
title: 💊 设计模式
order: 6
---
## 发布订阅者模式
定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使它们能够自动更新自己,当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
### 简单版
```js
// 主题 保存状态,状态变化之后触发所有观察者对象
class Subject {
constructor() {
this.state = 0
this.observers = []
}
getState() {
return this.state
}
setState(state) {
this.state = state
this.notifyAllObservers()
}
notifyAllObservers() {
this.observers.forEach(observer => {
observer.update()
})
}
attach(observer) {
this.observers.push(observer)
}
}
// 观察者
class Observer {
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
update() {
console.log(`${this.name} update, state: ${this.subject.getState()}`)
}
}
// 测试
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('02', s)
s.setState(12)
```
### 复杂版
```js
/**
* 发布订阅者模式
*/
export default class EventEmitter {
constructor() {
this.subs = {}
}
on(event, cb) {
(this.subs[event] || (this.subs[event] = [])).push(cb)
}
trigger(event, ...args) {
this.subs[event] &&
this.subs[event].forEach(cb => {
cb(...args)
})
}
once(event, onceCb) {
const cb = (...args) => {
onceCb(...args)
this.off(event, onceCb)
}
this.on(event, cb)
}
off(event, offCb) {
if (this.subs[event]) {
let index = this.subs[event].findIndex(cb => cb === offCb)
this.subs[event].splice(index, 1)
if (!this.subs[event].length) delete this.subs[event]
}
}
}
```