发布订阅模式 观察者模式
发布订阅是主动的,来个例子,我有一个女朋友,要包,要车。等我有钱了,买包买车。这个过程中,我要先订阅买包买车,等有钱了在发布。
观察者被动执行。我先观察你,你有变化了,我在变化,有点儿类似vue watch
发布订阅
例子1
先把想干的事情存起来,当真的发生时候,依次将数组中的内容执行。对应关系如下:
{
有钱: [买包,买车]
女生失恋: [哭,喝酒]
}
复制代码
代码实现:
let EventEmitter = require('events');
let util = require('util');
// 定义一个类
function Girl() {
}
// 继承共有方法
util.inherits(Girl, EventEmitter);
let girl = new Girl();
let cry = () => {
console.log('哭');
}
let drink = () => {
console.log('喝酒');
}
// 绑定对应方法
girl.on('女生失恋', cry);
girl.on('女生失恋', drink);
// 默认情况下是不执行的
// 触发执行
girl.emit('女生失恋');
复制代码
模拟实现发布订阅
- 定义一个类
<!--新建文件events.js-->
// 定义一个类
function EventEmitter() {
}
// 导出
module.exports = EventEmitter;
复制代码
- 定义好 on 和 emit 方法
// 定义一个类
function EventEmitter() {
}
// 订阅
EventEmitter.prototype.on = function() {
}
// 发布
EventEmitter.prototype.emit = function() {
}
// 导出
module.exports = EventEmitter;
复制代码
- 首先先维护一个对象,对象对应
{ '女生失恋': ['喝酒fn', '哭fn'] }
:
// 定义一个类
function EventEmitter() {
// 维护一个对象
// {
// '女生失恋': ['哭', '喝酒']
// }
this._events = {};
}
// 订阅
EventEmitter.prototype.on = function(type, callback) {
// 如果取不到_events 默认给空对象
if (!this._events){
this._events = {};
}
// 对象中存在
if (this._events[type]) {
this._events[type].push(callback);
} else {
this._events[type] = [callback];
}
}
复制代码
- 当执行 emit 时候将数组中的函数依次执行
// 发布
EventEmitter.prototype.emit = function(type) {
// 存在数组
if (this._events[type]) {
this._events[type].forEach(fn => {
// 此处的 fn 就是 喝酒, 哭
fn();
});
}
}
复制代码
- 解绑方法
EventEmitter.prototype.removeListener = function(type, callback) {
// 找到数组中对应方法移除。
if (this._events[type]) {
this._events[type] = this._events[type].filter(fn => {
return fn != callback;
})
}
}
// 外界调用
// 解绑事件
girl.removeListener('女生失恋', cry);
复制代码
- 添加 newListener 方法获取当前监听什么事件名字。
当前监听的如果不是 newListener 时候。执行 newListener 方法把当前 type 传递给回调函数,这样外界就可以获取 type 了
// 订阅
EventEmitter.prototype.on = function(type, callback) {
if (type !== 'newListener') {
this._events['newListener'].forEach(fn => {
fn(type);
})
}
// 如果取不到_events 默认给空对象
if (!this._events){
this._events = {};
}
// 对象中存在
if (this._events[type]) {
this._events[type].push(callback);
} else {
this._events[type] = [callback];
}
}
// 外界调用
girl.on('newListener', (type) => {
console.log(type);
})
复制代码
- 其他方法
// 默认最大监听
EventEmitter.defaultMaxListener = 10;
// 设置最大监听
EventEmitter.prototype.setMaxListeners = function(count) {
this._count = count;
}
// 获取最大监听
EventEmitter.prototype.getMaxListeners = function(count) {
return this._count || EventEmitter.defaultMaxListener;
}
// 获取 eventName
EventEmitter.prototype.eventNames = function() {
return Object.keys(this._events);
}
// 获取监听方法
EventEmitter.prototype.listeners = function(type) {
return this._events[type];
}
// 移除所有监听
EventEmitter.prototype.removeAllListeners = function(type) {
if (type) {
return this._events[type] = [];
};
this._events = {};
}
复制代码
代码:
event.js
// 定义一个类
function EventEmitter() {
// 维护一个对象
// {
// '女生失恋': ['哭', '喝酒']
// 'newListener': []
// }
this._events = {};
}
// 订阅
EventEmitter.prototype.addListener = EventEmitter.prototype.on = function(type, callback) {
// 如果取不到_events 默认给空对象
if (!this._events) {
this._events = Object.create(null);
}
if (type !== 'newListener' && this._events['newListener'] && this._events['newListener'].length) {
this._events['newListener'].forEach(fn => {
fn(type);
})
}
// 对象中存在
if (this._events[type]) {
this._events[type].push(callback);
} else {
this._events[type] = [callback];
}
// 如果超限制提示错误
if (this._events[type].length === this.getMaxListeners()) {
console.warn('memory link detected');
}
}
// 发布
EventEmitter.prototype.emit = function(type, ...args) {
// 存在数组
if (this._events[type]) {
this._events[type].forEach(fn => {
// 此处的 fn 就是 喝酒, 哭
fn(...args);
});
}
}
EventEmitter.prototype.removeListener = function(type, callback) {
// 找到数组中对应方法移除。
if (this._events[type]) {
this._events[type] = this._events[type].filter(fn => {
return fn != callback && fn.l !== callback;
})
}
}
// 默认最大监听
EventEmitter.defaultMaxListener = 10;
// 设置最大监听
EventEmitter.prototype.setMaxListeners = function(count) {
this._count = count;
}
// 获取最大监听
EventEmitter.prototype.getMaxListeners = function(count) {
return this._count || EventEmitter.defaultMaxListener;
}
// 获取 eventName
EventEmitter.prototype.eventNames = function() {
return Object.keys(this._events);
}
// 获取监听方法
EventEmitter.prototype.listeners = function(type) {
return this._events[type];
}
// 移除所有监听
EventEmitter.prototype.removeAllListeners = function(type) {
if (type) {
return this._events[type] = [];
};
this._events = {};
}
// once 先绑定 wrap 函数当执行完后从数组中删除。
EventEmitter.prototype.once = function(type, callback) {
// 添加一个包裹函数。
let wrap = (...args) => {
callback(...args);
this.removeListener(type, wrap);
}
// 将callback保存在 wrap.l上
wrap.l = callback;
this.on(type, wrap);
}
// 导出
module.exports = EventEmitter;
复制代码
调用:
let EventEmitter = require('./events');
let util = require('util');
// 定义一个类
function Girl() {
// EventEmitter.call(this);
}
// 继承共有方法
util.inherits(Girl, EventEmitter);
let girl = new Girl();
let cry = (a, b) => {
console.log('哭', a, b);
}
let drink = (a, b) => {
console.log('喝酒', a, b);
}
// girl.setMaxListeners(1);
// console.log(girl.getMaxListeners());
girl.on('newListener', (type) => {
// console.log(type, '哈哈哈');
})
// 绑定对应方法
girl.once('女生失恋', cry);
// girl.on('女生失恋', drink);
// 解绑事件
// girl.removeListener('女生失恋', cry);
// 默认情况下是不执行的
// 触发执行
girl.emit('女生失恋', 1, 2);
girl.emit('女生失恋');
girl.emit('女生失恋');
// 获取最大监听
// console.log(EventEmitter.defaultMaxListener);
// 获取 eventNames [ 'newListener', '女生失恋' ]
// console.log(girl.eventNames());
console.log(girl.listeners('女生失恋'));
复制代码