1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 浅谈Nodejs观察者模式【node.js】

浅谈Nodejs观察者模式【node.js】

时间:2019-06-04 16:28:38

相关推荐

浅谈Nodejs观察者模式【node.js】

web前端|js教程

Nodejs观察者模式

web前端-js教程

A、前言

thinkphp交友源码,ubuntu 看代码工具,tomcat区分系统吗,爬虫 起始url,云主机部署php,SEO薪酬SEO薪酬lzw

Nodejs使用有些日子了,近来再回顾下其API、多使用新特性,以期有更高层次的掌握,本次API的总结区别于单纯对英文版的汉化,会多做些扩展和自己的理解,希望对大家有所帮助,先从最核心的Events开始

商城上传照片功能源码,vscode数组的相加,ubuntu 打印乱码,tomcat收费么,嵌入式开发sqlite,python爬虫会把网站爬崩吗,php 去掉重复的值,千山优化seo,网站登录模板 ui,php 发送网页邮件,oa移动办公系统模板lzw

Nodejs的Events实现了一种观察者模式,其支持了Nodejs的核心机制,且http / fs / mongoose等都继承了Events,可以添加监听事件。这种设计模式在客户端的组件编程思想里经常会用到,我们先简单了解下该模式。

微信群发工具源码,ubuntu18病毒,tomcat启动错误代码5,网站控制爬虫状态,ksweb安装低版本php,东城必应seolzw

首次接触 观察者模式是在Extjs框架的 Ext.util.observable源码,那时刚接触js,感觉这种模式很强大,也是我最早接触到的设计模式,后来在 underscore.js 源码里也有看到,且后者实现更简捷、优雅,我编写组件时也基本是按照这种思想。

观察者模式就是为某一对象添加一监听事件,如on(‘show’, callback),由该对象在符合条件如show时自行触发,浏览器本身已经为dom实现了监听机制。

如我们为input添加keyup监听,目的是为了输出其value

$( input ).on( keyup, function(){ console.log( this.value );} );

这样输入内容时会自行在日志中输出其value。

但我们自己做一个组件如Dialog,如何监听最常用的show / hide事件呢?

初级的做法是实例化时直接将回调配置进去,如

var dialog = new Dialog({ content: 这里是弹出框的内容, show: function(){ console.log( 当弹框时输出此段内容 ); }});

这样也可以用,不过显然不够灵活,如何将dialog做的像input那样可随时添加事件呢

B、观察者模式实现

首先实现Events对象,这里提供基础的监听on和触发emit,事件是以json形式压栈在对象的_events里

var Events = { on: function( name, callback){ this._events = this._events || {}; this._events[ name ] = this._events[ name ] || []; this._events[ name ].push( callback ); }, emit: function( name ){ this._events = this._events || {}; var args = Array.prototype.slice.call( arguments, 1 ), me = this; if( this._events[ name ] ){$.each( this._events[ name ], function( k, v ){ v.call( me, args );} ) } } }

再抽象一个函数用于为对象复制属性

function extend( source ){ var args = Array.prototype.slice.call( arguments, 1 ); for( var i = 0, parent; parent = args[i]; i++ ){ for( var prop in parent ){source[ prop ] = parent[ prop ]; } }}

实现一个Dialog,

仅实现创建; method: show / hide; event: show / hide;

看效果时,加上这段样式

.dialog{ position: fixed; top: 50%; left: 50%; margin: -50px 0 0 -100px; width: 200px; height: 120px; background: #fff; border: 5px solid #afafaf;}

实现组件

var Dialog = function( config ){ this.config = config; this.init( this.config );};

扩展属性

extend( Dialog.prototype, { init: function( config ){ this.render( config ) }, render: function( config ){ this.el = $(

).addClass( dialog ); this.el.html( config.content ); $( ody ).append( this.el ); }, show: function( param ){ this.el.fadeIn(); this.emit( show, param ); }, hide: function( param ){ this.el.fadeOut(); this.emit( hide, param ); }}, Events );生成实例,并为其添加三个show及hide监听事件

var dialog = window.dialog = new Dialog({ content: dialog one});dialog.on( show, function( txt ){ console.log( dialog show one + txt );} );//do somethingdialog.on( show, function( txt ){ console.log( dialog show two + txt );} );//do somethingdialog.on( show, function( txt ){ console.log( dialog show three + txt );} );//do somethingdialog.on( hide, function( txt ){ console.log( dialog hide one + txt );} );//do somethingdialog.on( hide, function( txt ){ console.log( dialog hide two + txt );} );//do somethingdialog.on( hide, function( txt ){ console.log( dialog hide three + txt );} );

我们分六次添加了六个不同的show事件和hide事件。

当执行 dialog.show() 时就会输出三条对应的日志。添加的事件保存在 dialog._events里,如图

添加的三个show都输出成功,事件保存在_events属性里

nodejs Events也是实现了这一过程。

C、结构

var Events = require( events );console.log( Events );/*输出如下数据,可以看出 Events指向其EventEmiter{ [Function: EventEmitter] EventEmitter: [Circular], usingDomains: [Getter/Setter], defaultMaxListeners: 10, init: [Function], listenerCount: [Function] }*/var myEmitter = new Events();console.log( myEmitter );/*{ domain: null, _events: {}, //可以看到实例本身也有_events属性,添加的监听的事件就保存在这里 _maxListeners: undefined}*/console.log( myEmitter.__proto__ );/*{ domain: undefined, _events: undefined, _maxListeners: undefined, setMaxListeners: [Function: setMaxListeners], emit: [Function: emit], addListener: [Function: addListener], on: [Function: addListener], once: [Function: once], removeListener: [Function: removeListener], removeAllListeners: [Function: removeAllListeners], listeners: [Function: listeners] }*/myEmitter.on( show, function( txt ){ console.log( one + txt )})myEmitter.on( show, function( txt ){ console.log( ow + txt )})myEmitter.on( hide, function( txt ){ console.log( one + txt )})myEmitter.emit( show, show );myEmitter.setMaxListeners( 10 );console.log( myEmitter );/*{ domain: null, _events: { show: [ [Function], [Function] ], hide: [Function] }, //添加后的事情,以json形式存放 _maxListeners: 10 }*/

D、API

其提供的method有on,是addListener的简写都是为实例添加监听事件,其它属性也都顾名思义,就简单说明下

property_events: undefined, //以压栈形式存放on进来的事件_maxListeners: undefined //设置最大监听数,超出提warn----------------------------------------------------------------------------------------------------------------methodsetMaxListeners: [Function: setMaxListeners], /*设置私有属性_maxListeners的值,默认Events会在当某监听事件多于10个时发现警告(见上面Events.defaultMaxListeners),以防止内存泄露,如(node) warning: possible EventEmitter memory leak detected. 11 show listeners added. Use emitter.setMaxListeners() to increase limit.但这只是个友好的提醒,可以通过设置最大监听数来规避这个问题myEmitter.setMaxListeners( 20 );*/emit: [Function: emit], /*触发监听事件emitter.emit( event, [arg1], [arg2], ... )如myEmitter.on( show, prompt content ); 参数1为事件名,参数二供on回调里的参数 */addListener: [Function: addListener], /*添加监听事件emitter.addListener( event, listener );如 myEmitter.addListener( show, function( txt ){ console.log( txt ) } );参数一是事件名,参数二是对应的回调,回调里的参数就是 emit里的arguments.prototype.slice.call(1); */on: [Function: addListener], /*是addListener简写 */once: [Function: once], /*作用同 on,不过emit一次后就失效了emitter.once( event, listener );如 myEmitter.once( show, function( txt ){ console.log( txt ) } );当myEmitter.emit执行第二次时没有输出 */removeListener: [Function: removeListener], /*移除指定事件的指定回调,此时回调不能再用匿名函数。emitter.removeListener( event, listener );如 function show( txt ){ console.log( txt ) };myEmitter.on( show, show );console.log( myEmitter._events ); // { show: [ Function: show ] }myEmitter.removeListener( show, show ); console.log( myEmitter._events ); // {} */removeAllListeners: [Function: removeAllListeners], /* 删除指定事件的所有回调 emitter.removeAllListeners( [ event ] ); 如 myEmitter.removeAllListeners( show ); //删除所有show监听 myEmitter.removeAllListeners(); //删除所有监听 */listeners: [Function: listeners]/*查看指定监听emitter.listeners( event );如 myEmitter.listeners( show ); //返回一个数组同我们前面使用的 myEmitter._events[ show ]*/另外Events类本身提供了一个方法Events.listenerCount( emitter, event ); 获取指定实例下指定监听数如 Event.listenerCount( myEmitter, show )-----------------------------------------------------------------------------------------------还有两个eventnewListener / remoteListener,分别应用于为实例添加( on / once )和删除( removeListener ) 操作。emitter.on( event, listener );emitter.on( ewListener, function( event, listener ){ console.log( emitter.listeners( show ) ); //注意,此时监听还并没有添加到 emitter.listeners console.log( arguments ); }); emitter.on( emoveListener, function(){ console.log( emitter.listeners( show ) ); console.log( arguments ); })

E、应用

使用Events,通常就直接实例化即可,如上面API部分所例

不过,如果我们在nodejs端也实现了一个组件,如前面的Dialog,如何让Dialog也具备Events的功能呢?可以用Extjs实现的 extend方案

创建Dialog构建器

var Dialog = function(){ //do something}//抽象apply函数,提供属性的深度复制,同上面的extendfunction apply( source ){ var args = Array.prototype.slice.call( arguments, 1 ); for( var i = 0, parent; parent = args[i]; i++ ){ for( var prop in parent ){source[ prop ] = parent[ prop ]; } }}//抽象extend函数,用于实现继承var extend = function(){ // inline overrides var io = function(o){ for(var m in o){this[m] = o[m]; } }; var oc = Object.prototype.constructor; return function(sb, sp, overrides){ if(typeof sp == object){overrides = sp;sp = sb;sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; } var F = function(){},sbp,spp = sp.prototype; F.prototype = spp; sbp = sb.prototype = new F(); sbp.constructor=sb; sb.superclass=spp; if(spp.constructor == oc){spp.constructor=sp; } sb.override = function(o){apply(sb, o); }; sbp.superclass = sbp.supr = (function(){return spp; }); sbp.override = io; apply(sb, overrides); sb.extend = function(o){return extend(sb, o);}; return sb; };}();//将Events属性继承给DialogDialog = extend( Dialog, Events );//为Dialog新增 method show,其内触发 event showDialog.prototype.show = function( txt ){ this.emit( show, txt );}var dialog = new Dialog();//添加监听事件showdialog.on( show, function(txt){ console.log( txt )});//执行method show时,就会触发其内定义的show events,输出 this is showdialog.show( his is show );

这样就为一个组件实现了Events机制,当调用method时,会触发event

F、总结

nodejs提供了很好的监听机制,并且也应用在其所有模块,其支持了nodejs最特色的I/O模式,如我们启动http服务时会监听其 connect / close,http.request时会监听 data / end等,了解监听机制对学习理解nodejs的基础,也对提升编程思想有益。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。