This article mainly introduces the Nodejs observer mode. For more information, see
I. Preface
Nodejs has been used for a few days. Recently, I will review its API and use more new features in order to have a higher level of understanding. The summary of this API is different from the Chinese version alone, I will do more expansion and my own understanding. I hope it will help you, starting with the core Events.
The Events of Nodejs implements an observer mode. It supports the core mechanism of Nodejs, and http/fs/mongoose inherits Events and can add listening Events. This design pattern is often used in the component programming idea of the client. Let's first briefly understand this pattern.
The first contact with the observer mode is in Ext. util. the observable source code was just introduced to js. I felt that this mode was very powerful and was also the first design mode I came into contact with. Later, I went to underscore. js source code is also seen, and the latter implementation is simpler and more elegant, I also basically follow this idea when writing components.
The observer mode adds a listener event for an object, such as on ('show', callback). This event is triggered when the object meets the show condition, the browser itself has implemented a listening mechanism for dom.
For example, we add a keyup listener for input to output its value.
$( 'input' ).on( 'keyup', function(){ console.log( this.value );} );
In this way, the value of the input content is output in the log.
But how do we monitor the most common show/hide events by making a component such as Dialog?
The primary practice is to directly configure the callback during instantiation, as shown in figure
Var dialog = new Dialog ({content: 'Here is the content in the pop-up box ', show: function () {console. log ('output the content of this segment when the bullet box ');}});
This can also be used, but it is obviously not flexible enough. How can we add events at any time as input does the dialog?
Ii. Observer mode implementation
First, implement the Events object. Here, the basic listening on and emit triggering are provided. The event is pushed to the _ events of the object in json format.
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 ); } ) } } }
Abstract A function to copy attributes of an object.
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 ]; } }}
Implement a Dialog,
Create only; method: show/hide; event: show/hide;
Add this style when watching the effect
.dialog{ position: fixed; top: 50%; left: 50%; margin: -50px 0 0 -100px; width: 200px; height: 120px; background: #fff; border: 5px solid #afafaf;}
Implementation Components
var Dialog = function( config ){ this.config = config; this.init( this.config );};
Extended attributes
extend( Dialog.prototype, { init: function( config ){ this.render( config ) }, render: function( config ){ this.el = $( '' ).addClass( 'dialog' ); this.el.html( config.content ); $( 'body' ).append( this.el ); }, show: function( param ){ this.el.fadeIn(); this.emit( 'show', param ); }, hide: function( param ){ this.el.fadeOut(); this.emit( 'hide', param ); }}, Events );
Generate an instance and add three show and hide listening events to it
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 );} );
We added six different show events and hide events six times.
When dialog. show () is executed, three corresponding logs are output. The added events are saved in dialog. _ events,
All three show Files Added are output successfully, and the events are saved in the _ events attribute.
Nodejs Events also implements this process.
Iii. Structure
Var Events = require ('events'); console. log (Events);/* output the following data. It can be seen that Events point to its EventEmiter {[Function: EventEmitter] EventEmitter: [Circular], usingDomains: [Getter/Setter], defamaxmaxlisteners: 10, init: [Function], listenerCount: [Function]} */var myEmitter = new Events (); console. log (myEmitter);/* {domain: null, _ events: {}, // you can see that the instance also has the _ events attribute, the added listening event is saved here _ 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 ('two' + 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]}, // The added items are stored in json format _ maxListeners: 10 }*/
Iv. API
The method provided by addListener is on, which is short for adding listening events to instances. Other attributes are just as the name suggests.
Property_events: undefined, // store the Event _ maxListeners: undefined in the form of a pressure stack // set the maximum number of listeners, exceeding the threshold methodsetMaxListeners: [Function: setMaxListeners], /* set the value of the private attribute _ maxListeners. By default, Events will receive a warning when there are more than 10 listening Events (see the above Events. defamaxmaxlisteners) to prevent memory leakage, such as (node) warning: possible EventEmitter memory leak detected. 11 show listeners added. use emitter. setMaxListeners () to increase limit. however, this is only a friendly reminder. You can set the maximum number of listeners to avoid this problem. setMaxListeners (20); */emit: [Function: emit],/* trigger the listening event emitter. emit (event, [arg1], [arg2],...) for example, myEmitter. on ('show', 'prompt content'); parameter 1 is the event name. Parameter 2 is the parameter */addListener: [Function: addListener] In the on callback. /* Add the listening event emitter. addListener (event, listener); for example, myEmitter. addListener ('show', functi On (txt) {console. log (txt)}); parameter 1 is the event name, parameter 2 is the corresponding callback, and the parameter in the callback is arguments in emit. prototype. slice. call (1); */on: [Function: addListener],/* is the abbreviation of addListener */once: [Function: once],/* works with on, however, emit becomes invalid once. once (event, listener); for example, myEmitter. once ('show', function (txt) {console. log (txt)}); When myEmitter. the second execution of emit does not output */removeListener: [Function: removeListener],/* removes the specified callback of the specified event. At this time, the callback cannot use an anonymous Function. Emitter. removeListener (event, listener); for example, 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],/* Delete all the callback emitter of the specified event. removeAllListeners ([event]); for example, myEmitter. removeAllListene Rs ('show'); // delete all show listening myEmitter. removeAllListeners (); // delete all listeners */listeners: [Function: listeners]/* view the specified listener emitter. listeners (event); for example, myEmitter. listeners ('show'); // returns an array of myEmitter. _ events ['show'] */In addition, the Events class provides a method Events. listenerCount (emitter, event); obtains the specified number of listeners under the specified instance, such as Event. listenerCount (myEmitter, 'show ')------------------------------------------------------------------------ ----------------------- There are two eventnewListener/remoteListener, which are applied to add (on/once) and delete (removeListener) operations for the instance respectively. Emitter. on (event, listener); emitter. on ('newlistener ', function (event, listener) {console. log (emitter. listeners ('show'); // note that the listener has not been added to emitter. listeners console. log (arguments) ;}); emitter. on ('removelistener ', function () {console. log (emitter. listeners ('show'); console. log (arguments );})
V. Application
Events can be directly instantiated, as shown in the above API section.
However, if we have also implemented a component in nodejs, such as the previous Dialog, how can we make the Dialog have the Events function? Extend solution that can be implemented using Extjs
Create a Dialog Builder
Var Dialog = function () {// do something} // Abstract The apply function, which provides deep copying of attributes. The extendfunction applies (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] ;}}// abstract extend function, used to inherit var extend = function () {// inline overrides var io = function (o) {for (var m in o) {this [m] = o [m] ;}}; var oc = Ob Ject. 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 () {}, systolic, spp = sp. prototype; F. prototype = spp; BMI = sb. prototype = new F (); BMI. constructor = sb; sb. superclass = spp; if (spp. constructor = oc) {spp. constructor = sp;} sb. override = function (o) {apply (sb, o) ;}; BMI. superclass = systolic. supr = (function () {return spp;}); BMI. override = io; apply (sb, overrides); sb. extend = function (o) {return extend (sb, o) ;}; return sb ;}(); // inherit the Events attribute to DialogDialog = extend (Dialog, events); // Add method show for Dialog, which triggers event showDialog. prototype. show = function (txt) {this. emit ('show', txt);} var dialog = new Dialog (); // Add a listener event showdialog. on ('show', function (txt) {console. log (txt)}); // when method show is executed, the show events defined in it is triggered, and this is showdialog output. show ('this is show ');
In this way, the Events mechanism is implemented for a component. When method is called, the event
Vi. Summary
Nodejs provides a good listening mechanism and is also applied to all its modules. It supports the node. js's most distinctive I/O mode, for example, when we start the http service, we will listen to its connect/close, http. the request will listen to data/end and so on. Understanding the listening mechanism is also helpful for learning and understanding nodejs.