观察者模式:又称发布订阅模式,其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知

数据格式

1
2
3
4
5
6
7
8
9
10
11
12
const PubSub = {
// 订阅的唯一id
id: 1,
// 频道与回调保存容器
callbacks: {
// 频道,以及频道下消息和回调的对应列表
// pay:{
// token_1:fn,
// token_2:fn
// }
}
}

订阅消息

1
2
3
4
5
6
7
8
9
10
11
12
// 订阅消息
PubSub.subscribe = function (channel, callback) {
// 创建唯一的编号
let token = 'token_' + this.id++;
// 判断callbacks属性中是否存在
if (this.callbacks[channel]) {
this.callbacks[channel][token] = callback
} else {
this.callbacks[channel] = { [token]: callback }
}
return token
}

发布消息

当消息发布时,所有订阅了该消息的对象都将得到通知

1
2
3
4
5
6
7
8
9
// 发布消息
PubSub.publish = function (channel, data) {
// 获取当前频道中所有的回调
if (this.callbacks[channel]) {
Object.values(this.callbacks[channel]).forEach(callbcak => {
callbcak(data)
})
}
}

取消订阅

  1. 没有传值,flag 为undefined 取消订阅所有消息
  2. 传入token字符串 取消订阅某个对象
  3. msgName字符串 取消订阅某个频道
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    PubSub.unsubscribe = function (flag){
    if(flag === undefined){
    // 清空所有订阅
    this.callbacks = {}
    }else if(typeof flag === 'string'){
    // 判断是否是token_开头
    if(flag.indexOf('token_') === 0){
    // 是订阅id 找到对应订阅id
    let callbackObj = Object.values(this.callbacks).find(channel=>{
    return channel.hasOwnProperty(flag)
    })
    if(callbackObj){
    delete callbackObj[flag]
    }
    }else{
    // 是频道名称
    delete this.callbacks[flag]
    }
    }
    }

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
// 订阅一个频道
let pid = PubSub.subscribe('pay',(data)=>{
console.log('商家接到了订单,准备开始制作' + data.title)
})
let pid2 = PubSub.subscribe('pay',(data)=>{
console.log('骑手接到了订单,准备开始取餐' + data.pos)
})

PubSub.subscribe('cancel',(data)=>{
console.log('商家接到取消请求')
})

// PubSub.unsubscribe(pid)
PubSub.publish('pay',{
title:'鱼香肉丝',
price:20,
pos:'三年二班'
})
</script>