pub/sub这个应该大家用到的最广的设计 模式了
在这种模式中,并不是一个对象调用另一个对象的方法,而是一个对象订阅另一个对象
特定活动并在状态改变后获得通知,订阅者因此也成为观察者,而被观察的对象成为发布者或主题。当发生了一个重要事件的时候发布者会通知(调用)所有订阅者并且可能经常以事件对象的形式传递消息。
简单的实现发布订阅设计模式
// 创建EventBus
class EventBus {
constructor() {
// 储存事件
this.tasks = {};
}
// 绑定事件
$on(eName, cb) {
typeof cb == "function"
? this.tasks[eName] || (this.tasks[eName] = [])
: this.Error(cb, "is not a function");
this.tasks[eName].some(fn => fn == cb)
? true
: this.tasks[eName].push(cb); // 避免重复绑定
}
// 触发事件
$emit(eName, ...arg) {
let taskQueue;
this.tasks[eName] && this.tasks[eName].length > 0
? (taskQueue = this.tasks[eName])
: this.Error(eName, "is not defined or is a array of having empty callback");
taskQueue.forEach(fn => {
fn(...arg);
});
}
// 触发一次
$once(eName, cb) {
let fn = (...arg) => {
this.$off(eName, fn);
cb(...arg);
};
typeof cb == "function" && this.$on(eName, fn);
}
// 卸载事件
$off(eName, cb) {
let taskQueue;
this.tasks[eName] && this.tasks[eName].length > 0
? (taskQueue = this.tasks[eName])
: this.Error(eName, "is not exist");
if (typeof cb === "function") {
let index = taskQueue.findIndex(v => (v == cb));
index != -1 &&
taskQueue.splice(
taskQueue.findIndex(v => (v == cb)),
1
);
}
if (typeof cb === "undefined") {
taskQueue.length = 0;
}
}
// 异常处理
Error(node, errorMsg) {
throw Error(`${node} ${errorMsg}`);
}
}
我们针对自己的模式进行简单的使用:
// 首先定义一个事件池
const EventSinks = {
add(x, y) {
console.log("总和: " + x + y);
},
multip(x, y) {
console.log("乘积: " + x * y);
},
onceEvent() {
console.log("我执行一次后就自动卸载");
}
};
// 实例化对象
let bus = new EventBus();
bus.$on("operator", EventSinks.add); // 监听operator事件, 增加一个EventSinks.add
bus.$on("operator", EventSinks.add); // 当事件名和回调函数相同时,跳过,避免重复绑定
bus.$on("operator", EventSinks.multip); // 给operator事件增加一个EventSinks.multip回调函数
bus.$once("onceEvent", EventSinks.onceEvent); // 触发一次后卸载
console.log(bus.tasks); // { operator: [ [Function: add], [Function: multip] ], onceEvent: [ [Function: fn] ]}
bus.$emit("operator", 3, 5); // 总和:8 乘积:15
bus.$emit("onceEvent"); // 我就执行一次
console.log(bus.tasks); // { operator: [ [Function: add], [Function: multip] ], onceEvent: [] }
bus.$off("operator", EventSinks.add); // 卸载掉operator事件中的EventSinks.add函数体
console.log(bus.tasks); // { operator: [ [Function: multip] ], onceEvent: [] }
bus.$off("operator"); // 卸载operator事件的所有回调函数
console.log(bus.tasks); // { operator: [], onceEvent: [] }
bus.$emit("onceEvent"); // onceEvent is not defined or is a array of having empty callback