var Event = (function() {
var global = this,
Event,
_default = 'default'; Event = function() {
var _create,
_listen,
_trigger,
_remove,
_shift = Array.prototype.shift,
_unshift = Array.prototype.unshift,
namespaceCache = {},
each = function(ary, fn) {
var ret;
for (var i = 0, l = ary.length; i < l; i ++) {
var n = ary[i];
ret = fn.call(n, i, n);
};
return ret;
}; _listen = function(key, fn, cache) {
if (!cache[key]) {
cache[key] = [];
};
cache[key].push(fn);
}; _trigger = function() {
var cache = _shift.call(arguments),
key = _shift.call(arguments),
args = arguments,
_self = this,
stack = cache[key]; if (!stack || !stack.length) return; return each(stack, function() {
return this.apply(_self, args);
});
}; _remove = function(key, cache, fn) {
if (cache[key]) {
if (fn) {
for (var i = cache[key].length; i >= 0; i--) {
if (cache[key][i] === fn) {
cache[key].splice(i, 1);
};
};
} else {
cache[key] = [];
};
};
}; _create = function(namespace) {
var namespace = namespace || _default;
var cache = {},
offlineStack = [],
ret = { listen: function(key, fn, last) {
_listen(key, fn, cache);
if (offlineStack === null) return;
if (last === 'last') {
offlineStack.length && offlineStack.pop()();
} else {
each(offlineStack, function() {
this();
});
};
offlineStack = null;
}, trigger: function() {
var fn, args,
_self = this;
_unshift.call(arguments, cache);
args = arguments;
fn = function() {
return _trigger.apply(_self, args);
};
if (offlineStack) {
return offlineStack.push(fn);
};
return fn();
}, remove: function(key, fn) {
_remove(key, cache, fn);
}, one: function(key, fn, last) {
_remove(key, cache);
this.listen(key, fn, last);
} };
return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;
}; return { create: _create, one: function(key, fn, last) {
var event = this.create();
event.one(key, fn, last);
}, remove: function(key, fn) {
var event = this.create();
event.remove(key, fn);
}, listen: function(key, fn, last) {
var event = this.create();
event.listen(key, fn, last);
}, trigger: function() {
var event = this.create();
event.trigger.apply(this, arguments);
}
}; }(); return Event;
})();

使用姿势:

        /*// 先发布后订阅
event.trigger('evt1', 1, 2);
event.trigger('evt1', 3, 4); // 都存到offlineStack中去了 event.listen('evt1', e1); // 当有listen监听时,遍历offlineStack中的方法,发给第一次的listen
event.listen('evt1', e2);*/ /*// 先订阅后发布
event.listen('evt1', e1);
event.listen('evt1', e2); // 先订阅的事件都存到cache对象中去了 event.trigger('evt1', 1, 2); // 每次发布,都会遍历cache对象中对象事件名的数组
event.trigger('evt1', 3, 4); */ /*// 先发布后订阅 listen方法第三个参数可以是last,只有只会去多个trigger中的最后一个
event.trigger('evt1', 1, 2); // 1).
event.trigger('evt1', 3, 4); // 2). 都存到offlineStack中去了 event.listen('evt1', e1, 'last'); // 只会收到2).这个trigger*/ /*// 先订阅后发布再删除然后再发布,会发现evt1事件对象的cache[key]数组中少了e1函数,所以
// 再次发布只有e2执行了
event.listen('evt1', e1);
event.listen('evt1', e2); event.trigger('evt1', 1, 2);
event.remove('evt1', e1);
event.trigger('evt1', 3, 4);*/ // 订阅的再多,也只使用一个订阅
/*// 1). 先订阅后发布
event.one('evt1', e1);
event.one('evt1', e2); // 会使用这个,因为前一个被删了 event.trigger('evt1', 11, 22); // 所以会执行两次e2函数
event.trigger('evt1', 33, 44);*/ // 2). 先发布后订阅
/*event.trigger('evt1', 11, 22); // 所以会执行两次e2函数
event.trigger('evt1', 33, 44); event.one('evt1', e1); // 会使用这个,因为offlineStack被置为null了
event.one('evt1', e2); // 这个不执行了,需要等到下次trigger才会触发,因为e1从cache中删掉了,加入了e2, 如果后面还有one方法以此类推,会删除上一个监听的函数,添加新的监听函数*/ // 3). 先发布后订阅 one方法的第三个参数last会只接收最后一个trigger
event.trigger('evt1', 11, 22);
event.trigger('evt1', 33, 44); event.one('evt1', e2, 'last');
event.one('evt1', e1, 'last');

JavaScript设计模式 - 订阅发布模式(观察者模式)的更多相关文章

  1. 设计模式---订阅发布模式(Subscribe/Publish)

    设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...

  2. [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

  3. 学习javascript设计模式之发布-订阅(观察者)模式

    1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...

  4. js设计模式之代理模式以及订阅发布模式

    为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...

  5. Java里观察者模式(订阅发布模式)

    创建主题(Subject)接口 创建订阅者(Observer)接口 实现主题 实现观察者 测试 总结 在公司开发项目,如果碰到一些在特定条件下触发某些逻辑操作的功能的实现基本上都是用的定时器 比如用户 ...

  6. AngularJS的简单订阅发布模式例子

    控制器之间的交互方式广播 broadcast, 发射 emit 事件 类似于 js中的事件 , 可以自己定义事件 向上传递直到 document 在AngularJs中 向上传递直到 rootScop ...

  7. Publisher/Subscriber 订阅-发布模式

    Publisher/Subscriber 订阅-发布模式 本博后续将陆续整理这些年做的一些预研demo,及一些前沿技术的研究,与大家共研技术,共同进步. 关于发布订阅有很多种实现方式,下面主要介绍WC ...

  8. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  9. RabbitMQ下的生产消费者模式与订阅发布模式

    所谓模式,就是在某种场景下,一类问题及其解决方案的总结归纳.生产消费者模式与订阅发布模式是使用消息中间件时常用的两种模式,用于功能解耦和分布式系统间的消息通信,以下面两种场景为例: 数据接入   假设 ...

随机推荐

  1. Flask的Context(上下文)学习笔记

    上下文是一种属性的有序序列,为驻留在环境内的对象定义环境.在对象的激活过程中创建上下文,对象被配置为要求某些自动服务,如同步.事务.实时激活.安全性等等. 比如在计算机中,相对于进程而言,上下文就是进 ...

  2. canvas处理压缩照片并回显:https://cengjingdeshuige.oss-cn-beijing.aliyuncs.com/20180512/cannovs%E5%AD%A6%E4%B9%A0.html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. socket、web socket

    WEB SOCKET: 说明:为浏览器提供双工异步通信,浏览器可以向服务端发送消息.服务端也可以向浏览器发送消息. SOCKET: 说明:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接 ...

  4. JavaScript原型与原型链,原型的实际应用

    原型链是js面向对象的基础,非常重要. 一,创建对象的几种方法: 1,字面量 var o1 = { name:'o1' }; 2,构造函数 var M = function(name){ this.n ...

  5. 网络基础 Windows控制台下Ftp使用简介

    Windows控制台下Ftp使用简介 by:授客 QQ:1033553122 测试环境: ftp服务器所在主机ip:172.25.75.2 ftp用户目录:F:\ftp   C:\Users\laif ...

  6. android系统通过图片绝对路径获取URI的三种方法

    最近做项目要通过图片的绝对路径找到图片的URI,然后删除图片,小小总结一下获取URI的方法,亲自试验在 android 4.1.3的系统上都是可用的. 1.将所有的图片路径取出,遍历比较找到需要的路径 ...

  7. HBase中此类异常解决记录org.apache.hadoop.ipc.RemoteException(java.io.IOException):

    ERROR: Can't get master address from ZooKeeper; znode data == null   一定注意这只是问题的第一层表象,真的问题是: File /hb ...

  8. MySQL参数log_bin_trust_function_creators介绍-存储过程和复制

    MySQL的有个参数log_bin_trust_function_creators,官方文档对这个参数的介绍.解释如下所示: log_bin_trust_function_creators Comma ...

  9. 【PAT】B1054 求平均值(20 分)

    一开始就想用sscanf和sprintf去实现,但是没有设计好思路,卡住了. 看了网上别人的博客,都是用的很复杂的逻辑分别判断,一言不合就七八十航代码 今天早上看了柳神的代码,发现跟自己的思路一样,开 ...

  10. JavaScript中遍历数组和对象的方法

    js数组遍历和对象遍历 针对js各种遍历作一个总结分析,从类型用处,分析数组和对象各种遍历使用场景,优缺点等 JS数组遍历: 1,普通for循环,经常用的数组遍历 var arr = [1,2,0,3 ...