发布-订阅模式
我们在浏览博客或者阅读微信公众号的时候,当遇到喜欢的博主或者公众号,就会去关注他;当再有新的文章发布时,就会有文章更新的消息推送给我们,如此一来,就避免了我们不定时地翻阅。
看似简单的“关注”动作,就是典型的发布-订阅模式。在这里,文章的推送方叫做发布者,但文章并不会直接推送给订阅者,他们彼此之间可能不知道对方的存在。
用户将订阅公众号的事件注册到调度中心,公众号作为发布者,当有新文章发布时,公众号发布该事件到调度中心,调度中心会及时发消息告知用户。
一、JS实现思路
创建事件对象
事件订阅:on(事件名称(eventName),事件函数(callback))
判断事件名称是否存在,存在则添加到事件对象数组中;不存在则给eventlist添加eventName属性,属性值设置为空数组;
事件派发:emit(事件名称,[传递的参数])
判断事件名称是否存在,只有存在才将事件名称赋值给数组,然后遍历数组中的每一个函数,同时指向它,将params传递给每一个函数
事件解绑:off(事件名称,[解绑的函数])
判断解绑的函数是否存在,存在则判断事件名是否存在,存在则从数组中找到并删除事件名
如果解绑函数不存在,则将事件名对应的数组清空
const eventList = {};
//事件订阅: on(事件名称(eventName),事件函数(callback))
const $on = function (eventName, callback) {
if (!eventList[eventName]) {
eventList[eventName] = [];
}
eventList[eventName].push(callback);
}
//事件派发: emit(事件名称,[传递的参数])
const $emit = function (eventName, params) {
if (eventList[eventName]) {
var arr = eventList[eventName];
arr.forEach((cb) => {
cb(params);
})
}
}
// 事件解绑:(事件名称,[解绑的函数]):事件解绑
const $off = function (eventName, callback) {
if (callback) {
if (eventList[eventName]) {
var arr = eventList[eventName];
var index = arr.indexOf(callback);
arr.splice(index, 1)
}
} else {
eventList[eventName].length = 0;
}
}
function fn1(params) {
console.log(111, params)
}
function fn2(params) {
console.log(222, params)
}
function fn3(params) {
console.log(333, params)
}
$on("abc", fn1);
$on("abc", fn2);
$on("abc", fn3);
$off("abc",fn1);
$emit("abc", "abc");
console.log(eventList)
- 运行结果:
二、Node.js事件触发器events
const EventEmitter = require("events");
class MyEventEmitter extends EventEmitter{};
const myEventEmitter = new MyEventEmitter();
这里,自身的构造函数EventEmitter是不能被直接实例化的,必须要继承到子集上,让子集去实例化。
on:事件订阅
emit:事件触发
removeListener:移除一个事件
removeAllListener:移除所有的事件
once:只绑定一次函数
function fn1(val){
console.log(111,val)
}
function fn2(val){
console.log(222,val)
}
function fn3(val){
console.log(333,val)
}
myEventEmitter.on("handle",fn1)
myEventEmitter.on("handle",fn2)
myEventEmitter.once("handle",fn3)
myEventEmitter.removeListener("handle",fn1)
myEventEmitter.removeAllListeners("handle")
myEventEmitter.emit("handle","lxc")
myEventEmitter.emit("handle","lxc")
node index运行结果:
222 'lxc'
333 'lxc'
- setMaxListeners(n)
默认情况下,如果为特定事件添加了超过
10
个监听器,则EventEmitter
会打印一个警告。 这有助于发现内存泄露。 但是,并不是所有的事件都要限制10
个监听器。
setMaxListeners()
方法可以为指定的EventEmitter
实例修改限制。 值设为Infinity
(或0
)表示不限制监听器的数量。
三、vue
使用方式与Node.js基本相同
let vm = new Vue({
el: "#app"
})
function fn1(params) {
console.log("111", params)
}
function fn2(params) {
console.log("222", params)
}
function fn3(params) {
console.log("333", params)
}
vm.$on("handle", fn1);
vm.$on("handle", fn2);
vm.$once("handle", fn3);
vm.$off("handle", fn2);
vm.$emit("handle", "lxc");
vm.$emit("handle", "lxc");
将fn2解绑后,fn3只发布执行一次,所以运行结果:
111 lxc
333 lxc
111 lxc