理解并实现PubSub模式
假如我们正在构建一个类似于 Google Docs 的应用程序,当用户按下一个按键时,需要做的事情有很多: 新字符显示到屏幕上;插入点向后移动;将本次动作加入到撤销的历史记录中; 保持与服务器同步;拼写错误检查;统计字数和页数等等。
按照传统的做法,假如我们监听 keypress 事件,并在一个处理中完成所有的任务,这想想都觉得可怕了。 那么有没有什么方法可以更好的解决这个问题,答案就是分布式事件。
PubSub 模式,是 Publish/Subscribe 的缩写,意为“发布/订阅”模式。
在实际使用中,我们应该也会接触到 PubSub 模式,例如 Nodejs 中的 EventEmitter、Backbone 中的事件模型、以及 jQuery 中的事件。 以 EventEmitter 为栗子,它提供了 addListener(event, listener),removeListener(event, listener),emit(event, [arg1], [arg2], [...]) 方法。
var emitter = new EventEmitter(),
fn1 = function(value) {
console.log('fn1:', value);
},
fn2 = function(value) {
console.log('fn2:', value);
};
emitter.addListener('message', fn1);
emitter.addListener('message', fn2);
emitter.emit('message', 'test1');
emitter.removeListener('message', fn2);
emitter.emit('message', 'test2');
//fn1: test1
//fn2: test1
//fn1: test2
当调用 emit 方法时,会触发所有监听的事件。
就像上面说的,PubSub 其实很简单,现在我们来实现属于我们自己的 PubSub 对象。
首先创建 PubSub 类,增加 handlers 变量用于保存事件列表:
function PubSub() {
this.handlers = {};
}
添加事件时,将监听器加到数组中:
PubSub.prototype.on = function(type, listener) {
if (!(type in this.handlers)) {
this.handlers[type] = [];
}
this.handlers[type].push(listener);
};
删除事件时,移除监听器:
PubSub.prototype.off = function(type, listener) {
var i,
position = -1,
list = this.handlers[type],
length = this.handlers[type].length;
for (i = 0; i < length; i++) {
if (list[i] === listener) {
position = i;
break;
}
}
if (position === -1) {
return;
}
if (length === 1) {
delete this.handlers[type];
} else {
this.handlers[type].splice(position, 1);
}
};
触发事件,循环遍历并触发所有的事件:
PubSub.prototype.emit = function(type) {
var args = Array.prototype.slice.call(arguments, 1),
i,
list = this.handlers[type],
length = this.handlers[type].length;
for (i = 0; i < length; i++) {
list[i].apply(this, args);
}
};
测试:
var pubsub = new PubSub(),
fn1 = function(value) {
console.log('fn1:', value);
},
fn2 = function(value) {
console.log('fn2:', value);
};
pubsub.on('message', fn1);
pubsub.on('message', fn2);
pubsub.emit('message', 'test1');
pubsub.off('message', fn2);
pubsub.emit('message', 'test2');
//fn1: test1
//fn2: test1
//fn1: test2
注:更多的实现请看 Nodejs 中的 events.js。
转自:http://www.wenzhixin.net.cn/2013/11/06/understand_pubsub
理解并实现PubSub模式的更多相关文章
- MVC+EF 理解和实现仓储模式和工作单元模式
MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
- ZeroMQ中PUB-SUB模式测试
因为公司有需求,对程序模块之间通信效率有较高的需求.之前公司用的通信组件是ActiveMQ,根据网上公布的测试结果显示其效率比较低, 后来考虑准备在新的项目中开始使用ZeroMQ.看了几天发现用起来比 ...
- 理解 Android MVP 开发模式
/***************************************************************************************** * 理解 Andr ...
- 简单理解设计模式——享元模式-线程池-任务(tesk)
前面在写到多线程的文章的时候,一直想写一篇关于线程池等一系列的文章,做一下记录,本篇博客记录一下设计模式中享元模式的设计思想,以及使用享元模式的实现案例——线程池,以及线程池的简化版——任务(tesk ...
- ios--->OC中Protocol理解及在代理模式中的使用
OC中Protocol理解及在代理模式中的使用 Protocol基本概念 Protocol翻译过来, 叫做"协议",其作用就是用来声明一些方法: Protocol(协议)的作用 定 ...
- 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...
- 飘逸的python - 理解打开文件的模式
当我们用open()函数去打开文件的时候,有好几种打开的模式. 'r'->只读 'w'->只写,文件已存在则清空,不存在则创建. 'a'->追加,写到文件末尾 'b'->二 ...
- 我所理解的Android 启动模式
首先,这是从 一个开源网站转载的,觉得写得不错,对我们之前理解的activity的启动模式是一个新的理解方式,并给出实际的应用场景. 任务栈是什么 任务栈Task,是一种用来放置Activity实例的 ...
随机推荐
- DIOCP-开源项目ECHO测试.
DIOCP自开源以来,得到了很多朋友的测试,并进行了诸多的改进,现在已经运用到了一些具体的项目当中. DIOCP底层运行稳定. 昨天做了个ECHO测试,这个连接数并没有达到上限. 11K 连接,1个半 ...
- JAVA Zero Copy的相关知识【转】
转自:https://my.oschina.net/cloudcoder/blog/299944 摘要: java 的zero copy多在网络应用程序中使用.Java的libaries在linux和 ...
- alluxio网络流量异常分析【转】
1. 介绍 2. 准备工作 2.1 tcpdump 2.2 winshark 2.3 安装iftop 2.4 alluxio网络通信相关的端口 3.iftop 锁定消耗流量最大的端口 4. dump数 ...
- 【Android】输入设备配置文件(.idc文件)
何为idc idc(Input Device Configuration)为输入设备配置文件,它包含设备具体的配置属性,这些属性影响输入设备的行为. 对于touch screen设备,总是需要一个id ...
- hdu1599(无向图的最小环模板)
题意:杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至 ...
- Oracle锁表查询和解锁方法
数据库操作语句的分类 DDL:数据库模式定义语言,关键字:create DML:数据操纵语言,关键字:Insert.delete.update DCL:数据库控制语言 ,关键字:grant.remov ...
- C++客户端访问Java服务端发布的SOAP模式的WebService接口
gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以 简单快速地开发出SOAP/XML的服务器端和客户端 Step1 使用gsoap-2.8\gsoap\bin\win32\wsdl ...
- SpringMVC REST 风格静态资源访问配置
1 在web.xml中使用默认servlet处理静态资源,缺点是如果静态资源过多,则配置量会比较大,一旦有遗漏,则会造成资源无法正常显示或404错误. <!-- 静态资源访问控制 --> ...
- git——从远程库克隆
从远程库克隆 阅读: 248434 上次我们讲了先有本地库,后有远程库的时候,如何关联远程库. 现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆. 首先,登陆GitHub,创建 ...
- IEnumerable<T> 转换为数组
IEnumerable<User> userlist=xxxx; string[] ids=userlist.select(u=>u.id).toArray();