node.js笔记之订阅发布设计模式
2018-01-30 11:31
645 查看
当看多了node.js的程序后你会发现特别多的‘订阅发布模式’,大多都是这种监听事件,然后通过回调函数的方式来实现异步操作:
所以我又重新学习了一下此设计模式;
参考的文章:友情链接
讲得真的很赞,还有他的博客,值得好好研读学习;我是学习了他的例子,然后进行了解读和修改,不过也发现了此程序中的一个小bug;
代码思路:利用对象的
bug:当多个回调函数订阅了同一个事件后,然后想去解绑其中一个回调函数的时候,除了最后一个回调函数可以解除外,其余均无效.
这个原因值得注意一下:
上面是他出问题的代码,将这个循环展开看一下;
原因就是在于这个_fn在声明赋值的语句在循环外,值不会进行改变;所以会出现这样的情况,如果要改进的话可以这么改;
不过他整体代码还是很精练,值得我们学习,瑕不掩瑜~
改进的地方为:对于多个回调订阅同一事件的时候可以利用数组进行传入,不必每一个都调用listen进行绑定,解除绑定同理;
下面是我改进后的代码:
req.on('data',function(){ //do something }); req.on('end',function(){ //do something });
所以我又重新学习了一下此设计模式;
参考的文章:友情链接
讲得真的很赞,还有他的博客,值得好好研读学习;我是学习了他的例子,然后进行了解读和修改,不过也发现了此程序中的一个小bug;
代码思路:利用对象的
键-值作为事件和回调的映射:将我们需要监听的事件名称作为对象的属性,为其创建一个数组,然后将绑定在此事件下的回调函数传入数组进行保存,当触发事件的时候,依次执行数组中的回调函数即可;
bug:当多个回调函数订阅了同一个事件后,然后想去解绑其中一个回调函数的时候,除了最后一个回调函数可以解除外,其余均无效.
这个原因值得注意一下:
for (var i = fns.length - 1,_fn=fns[i]; i >= 0; i--) { if (_fn === fn) { // 删除订阅回调函数 fns.splice(i, 1); } }
上面是他出问题的代码,将这个循环展开看一下;
var i = fns.length - 1,_fn=fns[i]; while(i>=0) { if (_fn === fn) { // 删除订阅回调函数 fns.splice(i, 1); } i--; }
原因就是在于这个_fn在声明赋值的语句在循环外,值不会进行改变;所以会出现这样的情况,如果要改进的话可以这么改;
for (var i = fns.length - 1,_fn; _fn=fns[i]; i--) { if (_fn === fn) { // 删除订阅回调函数 fns.splice(i, 1); } }
不过他整体代码还是很精练,值得我们学习,瑕不掩瑜~
改进的地方为:对于多个回调订阅同一事件的时候可以利用数组进行传入,不必每一个都调用listen进行绑定,解除绑定同理;
下面是我改进后的代码:
var Event = (function () { var clientList = {}; var listen, trigger, remove; listen = function (key, fn) { if (!clientList[key]) { clientList[key] = []; } if (Object.prototype.toString.call(fn) == "[object Array]") { clientList[key] = clientList[key].concat(fn); return } clientList[key].push(fn); }; trigger = function () { //这里的arguments为调用trigger时传入的参数,以下面的例子来说为['login','处理'] //shift为删除数组的首元素,并返回被删除的这个元素 //这里的key为'login' var key = [].shift.call(arguments); var fns = clientList[key]; if (!fns || fns.length === 0) { return false; } for (var i = 0, fn; fn = fns[i++]; ) { //这里的arguments为['处理'] fn.apply(this, arguments); } }; remove = function (key, fn) { var fns = clientList[key]; var isArray = Object.prototype.toString.call(fn) == "[object Array]" ? true : false; var len = isArray ? fn.length : 1; // key对应的消息没有被人订阅 if (!fns) { return false; } // 没有传入fn(具体的回调函数), 表示取消key对应的所有订阅 if (!fn) { //数组是传址调用,所以这里相当于把clientList[key]清零 fns.length = 0; } else { // 反向遍历 for (var j = 0; j < len; j++) { for (var i = fns.length - 1; i >= 0; i--) { if (fns[i] === (isArray ? fn[j] : fn)) { // 删除订阅回调函数 fns.splice(i, 1); } } } } }; return { listen : listen, trigger : trigger, remove : remove } }()); function handler1(data) { console.log('1:' + data); } function handler2(data) { console.log('2:' + data); } function handler3(data) { console.log('3:' + data); } Event.listen('login', [handler1, handler2, handler3]); Event.remove('login', [handler1, handler2]); Event.trigger('login', '处理')
相关文章推荐
- 【学习笔记javascript设计模式与开发实践(发布--订阅模式)----8】
- java笔记--设计模式之观察者(订阅/发布)模式
- JS设计模式之发布订阅模式
- 【学习笔记javascript设计模式与开发实践(发布--订阅模式)----8】
- js设计模式中发布与订阅实现观察者模式例子
- node.js 发布订阅模式
- JS设计模式 - 观察者模式与发布/订阅模式
- 学习笔记-js发布/订阅模式的简单实现
- js设计模式之代理模式以及订阅发布模式
- node.js 发布订阅模式的实例
- Redis中multi,exec,watch,发布与订阅模式命令介绍笔记(9)
- js 发布订阅模式的实例讲解
- js-设计模式学习笔记-策略模式
- 设计模式---订阅发布模式(Subscribe/Publish)
- [转载]JS中什么是发布--订阅模式?
- node.js+redis+express 实现发布订阅功能
- 基于JS原生的事件订阅和发布模式代码
- 设计模式二:观察者模式(发布订阅模式)
- 【js设计模式笔记---单体模式】
- ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现