假如我们正在构建一个类似于 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模式的更多相关文章

  1. MVC+EF 理解和实现仓储模式和工作单元模式

    MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...

  2. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  3. ZeroMQ中PUB-SUB模式测试

    因为公司有需求,对程序模块之间通信效率有较高的需求.之前公司用的通信组件是ActiveMQ,根据网上公布的测试结果显示其效率比较低, 后来考虑准备在新的项目中开始使用ZeroMQ.看了几天发现用起来比 ...

  4. 理解 Android MVP 开发模式

    /***************************************************************************************** * 理解 Andr ...

  5. 简单理解设计模式——享元模式-线程池-任务(tesk)

    前面在写到多线程的文章的时候,一直想写一篇关于线程池等一系列的文章,做一下记录,本篇博客记录一下设计模式中享元模式的设计思想,以及使用享元模式的实现案例——线程池,以及线程池的简化版——任务(tesk ...

  6. ios--->OC中Protocol理解及在代理模式中的使用

    OC中Protocol理解及在代理模式中的使用 Protocol基本概念 Protocol翻译过来, 叫做"协议",其作用就是用来声明一些方法: Protocol(协议)的作用 定 ...

  7. 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...

  8. 飘逸的python - 理解打开文件的模式

    当我们用open()函数去打开文件的时候,有好几种打开的模式.   'r'->只读 'w'->只写,文件已存在则清空,不存在则创建. 'a'->追加,写到文件末尾 'b'->二 ...

  9. 我所理解的Android 启动模式

    首先,这是从 一个开源网站转载的,觉得写得不错,对我们之前理解的activity的启动模式是一个新的理解方式,并给出实际的应用场景. 任务栈是什么 任务栈Task,是一种用来放置Activity实例的 ...

随机推荐

  1. 每天一个linux命令(3):du命令

    Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是查看当前指定文件或目录(会递归显示子目录)占用磁盘空间大小,还是和df命令有一些区别的. 1.命令格式: du [选 ...

  2. 设置Chrome忽略网站证书错误

    本人在XP下使用Chrome.总是莫名其妙的提示整数错误,一部分https网站无法直接访问.网上找了下,把解决思路记录下来. 解决这个问题很简单,只需要修改你平时用来启动Chrome的快捷方式就可以忽 ...

  3. BootStrapTable 文档

    文档包含了表格属性.列属性.事件.方法等等. 表格参数 表格的参数定义在 jQuery.fn.bootstrapTable.defaults. 名称   标签   类型   默认   描述   - d ...

  4. Windows + Ubuntu双系统时间不一致

    在安装Ubuntu和Windows双系统的情况下,Ubuntu的时间总会和Windows的时间相差8小时,原因在于widows认为BIOS时间是本地时间,Ubuntu认为BIOS时间是UTC时间 su ...

  5. JAVA-数据库之添加记录

    相关资料:<21天学通Java Web开发> 添加记录1.使用语句对象Statement的executeUpdate()方法可以很方便地实现添加记录.2.只需要在executUpdae() ...

  6. Linux 常用命令随笔(一)

    Linux 常用命令随笔(一) 1.检查linux服务器的文件系统的磁盘空间 df -h 说明: -h更具目前磁盘空间和使用情况 以更易读的方式显示 -H根上面的-h参数相同,不过在根式化的时候,采用 ...

  7. <第一次买基金就赚钱>读书笔记

    基金,是指专门用于某种特定目的的并进行独立核算的资金 基金的开放日指基金契约规定的投资者可以在销售网点办理基金申购.赎回交易业务的日期 基金资产总值是指一个基金所拥有的资产(包括现金.股票.债券和其他 ...

  8. go语言简述

    Go是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易. Go语言被设计成一门应用于搭建web服务器,存储集群或类似用途的巨型中央服务器的系统编程语言.对于高性能分布式系统领域而言,Go语 ...

  9. linux下nc的使用

    发送端:cat test.txt | nc -l -p 6666或者nc -l  -p 6666 < test.txt                    有些版本不要在 -p[监听6666端 ...

  10. 【C】——网络编程-聊天室

    功能介绍: 此demo是基于TCP套接字编程,目的是实现一个聊天室效果.类似于QQ群效果,如果上线可以通知其他好友,下线也会通知其他好友. 需要用的技术: 一.socket编程. 1> sock ...