小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
导言
其实不难写,只要理解了它的三个核心:订阅列表,订阅,发布。三个概念就能很容易写出来。
实现
1. 思路
其实可以把发布订阅当做买卖房子来看:
- 订阅列表:购房者
- 订阅:订房者
- 发布:通知部
大概执行过程就是:订阅 -> 加入订阅列表 -> 通知
张三来订房,订好房后加入订阅列表,等有房时通知部会去通知他。
实现思路:维护一个数组类型的订阅列表,在添加两个订阅和发布方法,每次通过订阅者将订阅方法加入订阅列表中,而后通过发布方法通知订阅者。
2. 实现
const issue = {
// 订阅者队列
queue: [],
// 订阅
subscribe(type, func){
// 判断此类型在订阅列表中是否不存在
if(this.queue[type] == undefined){
// 如果不存在则将它以数组形式加入订阅列表中
this.queue[type] = []
}
// 将这个类型的方法加入当前类型中
this.queue[type].push(func)
},
// 发布
notification(type){
// 判断此类是否不存在
if(this.queue[type] == undefined){
throw '类型不存在'
}
// 遍历取出这个类型下的所有任务
for(let i = 0; i < this.queue[type].length; i++ ){
// 拿到这个类型下的每个任务
let funcs = this.queue[type][i]
// 判断有无带参数
if(arguments[1]){
// 存放参数
const args = []
// 拿到调用函数时的传值,声明 i 为 1,表示从第二个值开始拿
// 诺不然它会将第一个代表函数类型的值也拿到
for(let i = 1; i < arguments.length; i++){
// 这里对应数组中的位置减一,如果不减一,那么会直接在数组的第二位开始插入
// 这样会导致数组的第一项是个空值,且函数使用这个参数集会报 undefined 错误
args[i-1] = arguments[i]
}
// 调用执行并使用扩展运算符将 args 传进去
funcs(...args)
}else{
// 无参直接调用
funcs()
}
}
}
}
\