博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
你的发布订阅模式会用了吗
阅读量:7069 次
发布时间:2019-06-28

本文共 5637 字,大约阅读时间需要 18 分钟。

发布订阅

很多人javascript设计模式看了n遍,从不太理解到理解,再到每次看都了然于胸一天之后就忘得干干净净,其实应用起来或者写下来,也许你会理解得更彻底一些;

上代码吧

let event = {                                                   // event 事件对象    list: {},                                                   // event绑定的事件订阅列表    on(key, fn) {                                               // 添加事件绑定   key表示要添加绑定的事件类型        if (!this.list[key]) {                                  // 如果没有则创建空数组            this.list[key] = [];        }        this.list[key].push(fn);                                // push进该类型事件数组    },    emit() {        let key = [].shift.call(arguments),     //发布 取key值为emit的第一个参数            fns = this.list[key];        if (!fns || fns.length === 0) {         // 如果该事件订阅列表为空 返回false 这里不进行其他处理            return false;        }                                       // 如果该事件订阅列表存在,则依次执行        fns.forEach(fn => {                                   fn.apply(this, arguments);          // 这里的arguments已经删除了key值        });    },    remove(key, fn) {                           // 取消订阅        let fns = this.list[key];                 if (!fns) return false;                 // 如果缓存列表中没有函数,返回false        if (!fn) {                              // 如果没有传对应函数的话 就将key值对应缓存列表中的函数都清空掉            fns && (fns.length = 0);        } else {                                // 遍历缓存列表,看看传入的fn与哪个函数相同,如果相同就直接从缓存列表中删掉即可            fns.forEach((cb, i) => {                if (cb === fn) {                    fns.splice(i, 1);                }            });        }    }};// 测试function cat(data) {    console.log(data, '喵喵喵');}function dog(data) {    console.log(data, '旺旺旺');}function animal(data) {    console.log(data, '都是主子');}function pet(data) {    console.log(data, '都是动物');}event.on('animal',animal);event.on('animal', pet);event.on('cat', cat);event.on('dog', dog);// 发布event.emit('animal', ['藏獒', '喵星人']);event.emit('cat', ['喵星人']);event.emit('dog', ['藏獒']);// 取消dog方法的订阅event.remove('animal', pet);// 再次发布event.emit('animal', ['藏獒', '喵星人']);复制代码

很清晰了,接下来再聊一聊node的一个模块events吧

node 的 events模块的应用

// 监听的目的 就是为了构造这样一个对象 一对多的关系    on// 发布的时候 会让数组的函数依次执行                emitlet EventEmitter = require('events');               // 引入events模块class Girl extends EventEmitter{}                   // class继承let girl = new Girl();                              // new 一个Girl的实例let shopping = function (data) {                    // 购物    console.log(data, '去购物');};let dieting = function (data) {                      // 节食    console.log(data, '去节食');};girl.on('newListener', function (eventName) {        // 添加订阅的监听    console.log('新添加了订阅: ' + eventName);});girl.setMaxListeners(3);                               // 设置最大订阅数console.log('最大订阅数是:', girl.getMaxListeners());   // 打印最大订阅数girl.on('减肥', dieting);                              // 订阅减肥 girl.once('发工资', shopping);                         // 订阅发工资girl.prependListener('发工资', function () {        console.log('这是发工资前');});复制代码

当然这里是使用node的模块,那如果我想自己去实现一个这样的event模块呢

node 的 events模块的实现

上代码

function EventEmitter() {     // this._events = {};     // 用Object.create(null)代替空对象{}的好处是无杂质,不继承原型链     this._events = Object.create(null); } // 默认最多的绑定次数 EventEmitter.defaultMaxListeners = 10; // 同on方法 EventEmitter.prototype.addListener = EventEmitter.prototype.on; // 返回监听的事件名 EventEmitter.prototype.eventNames = function () {     return Object.keys(this._events); }; // 设置最大监听数 EventEmitter.prototype.setMaxListeners = function (n) {     this._count = n; }; // 返回监听数 EventEmitter.prototype.getMaxListeners = function () {     return this._count ? this._count : this.defaultMaxListeners; }; // 监听 EventEmitter.prototype.on = function (type, cb, flag) {     // 默认值,如果没有_events的话,就给它创建一个     if (!this._events) {         this._events = Object.create(null);     }     // 不是newListener 就应该让newListener执行以下     if (type !== 'newListener') {         this._events['newListener'] && this._events['newListener'].forEach(listener => {             listener(type);         });     }     if (this._events[type]) {         // 根据传入的flag来决定是向前还是向后添加         if (flag) {             this._events[type].unshift(cb);         } else {             this._events[type].push(cb);         }     } else {         this._events[type] = [cb]; }     // 监听的事件不能超过了设置的最大监听数     if (this._events[type].length === this.getMaxListeners()) {         console.warn('警告-警告-警告');     } }; // 向前添加 EventEmitter.prototype.prependListener = function (type, cb) {     this.on(type, cb, true); }; EventEmitter.prototype.prependOnceListener = function (type, cb) {     this.once(type, cb, true); }; // 监听一次 EventEmitter.prototype.once = function (type, cb, flag) {     // 先绑定,调用后删除     function wrap() {         cb(...arguments);         this.removeListener(type, wrap);     }     // 自定义属性     wrap.listen = cb;     this.on(type, wrap, flag); }; // 删除监听类型 EventEmitter.prototype.removeListener = function (type, cb) {     if (this._events[type]) {         this._events[type] = this._events[type].filter(listener => {             return cb !== listener && cb !== listener.listen;         });     } }; EventEmitter.prototype.removeAllListener = function () {     this._events = Object.create(null); }; // 返回所有的监听类型 EventEmitter.prototype.listeners = function (type) {     return this._events[type]; }; // 发布 EventEmitter.prototype.emit = function (type, ...args) {     if (this._events[type]) {         this._events[type].forEach(listener => {             listener.call(this, ...args);     }); }};module.exports = EventEmitter;复制代码

现在可以通过引入我们自己实现的event来进行测试了

//  let EventEmitter = require('events');               // 引入events模块let EventEmitter = require('./events');               // 引入events模块复制代码

That's all,如上;

转载地址:http://cehll.baihongyu.com/

你可能感兴趣的文章
Netty服务器连接池管理设计思路
查看>>
5.多个Storyboard切换
查看>>
Vue CLI 3开发中屏蔽烦人的EsLint错误
查看>>
批量分发管理三种解决方案案例视频分享
查看>>
Scrum方法论(四)
查看>>
处理windows 2008x64平台exchange 2010 sp1打完系统补丁后,控制台无法打开
查看>>
Windows Server 2016-命令行Ntdsutil迁移FSMO角色
查看>>
征服Perl——基础知识——里程碑M4
查看>>
linux svn服务器搭建、客户端操作、备份与恢复
查看>>
报表服务入门(实验4)创建共享数据源
查看>>
程序员娶妻子的经典准则
查看>>
Synology NAS 存储系统多路径连接Vmware ESXi 6.5
查看>>
K8s 原理架构介绍(一)
查看>>
微软正式发布OneDrive 提供100GB免费空间
查看>>
移动端web无刷新上传图片【兼容安卓IOS】
查看>>
MySQL-MongoDB开源监控利器PMM增加slack报警功能
查看>>
PowerShell 查找删除Windows补丁文件
查看>>
Powershell 创建文件,安全组和DFS链接
查看>>
在Linux系统中安装Subversion版本控制
查看>>
云计算的一匹黑马——SAP
查看>>