發佈訂閱是主動的,來個例子,我有一個女友,要包,要車。等我有錢了,買包買車。這個過程當中,我要先訂閱買包買車,等有錢了在發佈。vue
觀察者被動執行。我先觀察你,你有變化了,我在變化,有點兒相似vue watch數組
例子1bash
先把想幹的事情存起來,當真的發生時候,依次將數組中的內容執行。對應關係以下:函數
{
有錢: [買包,買車]
女生失戀: [哭,喝酒]
}
複製代碼
代碼實現:ui
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('女生失戀');
複製代碼
模擬實現發佈訂閱this
<!--新建文件events.js-->
// 定義一個類
function EventEmitter() {
}
// 導出
module.exports = EventEmitter;
複製代碼
// 定義一個類
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];
}
}
複製代碼
// 發佈
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 方法把當前 type 傳遞給回調函數,這樣外界就能夠獲取 type 了spa
// 訂閱
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 = {};
}
複製代碼
代碼:prototype
event.jscode
// 定義一個類
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('女生失戀'));
複製代碼