Node. js: most of the core APIs of the events event module Nodejs are designed based on asynchronous event drivers. All objects that can distribute events are EventEmitter instances.
As you know, Because nodejs runs in a single thread, nodejs needs to use event polling to constantly query event messages in the event queue and then execute the corresponding callback function of the event, similar to the Message ing mechanism in windows. For more detailed implementation steps, you can find additional information.
The following describes how to use EventEmitter.
1. Listen to events and distribute events
The EventEmitter instance can use on or addListener to listen to events. The emit () method distributes events as follows:
Const events = require ('events'), EventEmitter = events. eventEmitter, util = require ('til'); function myEmiter () {EventEmitter. call (this) ;}; util. inherits (myEmiter, EventEmitter); // inherits the EventEmitter class const myEmitterIns = new myEmiter (); myEmitterIns. on ('data', (o) => {console. log ('receive the data: '+ o. a );});
Or use the class
Class myEmiter extends EventEmitter {} // inherits EventEmitter class const myEmitterIns = new myEmiter (); myEmitterIns. on ('data', (o) => {console. log ('receive the data: '+ o. a) ;}); myEmitterIns. emit ('data', {a: 1 });
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
Receive the data: 1
2. Pass parameters to the event listening callback function
The preceding example shows that the emit () method can pass any set of parameters to the callback function. Note that the this keyword points to the EventEmiter instance that calls the emit method, except for the arrow function, this points to the global this, because this in the arrow function is bound at definition. As follows:
Class myEmiter extends EventEmitter {} const myEmitterIns = new myEmiter (); myEmitterIns. on ('data', function (data) {console. log ("this:" In the common callback function); console. log (this) ;}); myEmitterIns. on ('data1', (data1) => {console. log ("this:" In the arrow callback function); console. log (this) ;}); myEmitterIns. emit ('data', {a: 1}); myEmitterIns. emit ('data1', {a: 1 });
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
In the common callback function, this:
MyEmiter {
Domain: null,
_ Events: {data: [Function], data1: [Function]},
_ EventsCount: 2,
_ MaxListeners: undefined}
In the arrow callback function, this:
{}
Here we will talk about this in the arrow function. By the way, why does the arrow function bind this when it is implemented? this is because there is no internal binding mechanism of this in the arrow function, it uses this in the outer scope, so it cannot be used as a constructor.
3. execution sequence of event listening programs
The EventEmiter instance can bind multiple events. When we trigger these events sequentially, EventEmiter will be executed in synchronous mode. If the first event processing function is not completed, the next event will not be triggered, as follows:
Class myEmiter extends EventEmitter {} const myEmitterIns = new myEmiter (); myEmitterIns. on ('data', function (data) {console. time ('data event executed '); for (var I = 0; I <100000; I ++) for (var j = 0; j <100000; j ++); console. timeEnd ('data event executed ') ;}); myEmitterIns. on ('data1', (data1) => {console. log ("data1 event execution started... ") ;}); myEmitterIns. emit ('data', {a: 1}); myEmitterIns. emit ('data1', {a: 1 });
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
Data event execution: 4721.401 ms
Execute the data1 event...
Of course, we can use asynchronous operations in the callback function, such as setTimeout, setImmediate or process. nextTick (), to achieve the asynchronous effect, as shown below:
MyEmitterIns. on ('data', function (data) {setImmediate () => {console. log ('data event executed... ');});});
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
The data1 event is executed...
The data event is executed...
4. One-time event monitoring
EventEmiter can use once to listen to an event. The event handler will only trigger once, And the emit event will be ignored because the listener is canceled, as shown below:
myEmitterIns.once('one',(data)=>{ console.log(data);});myEmitterIns.emit('one','this is first call!');myEmitterIns.emit('one','this is second call!');
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
This is first call!
The preceding result shows that the 'one' event is executed only once.
5. Remove event binding
Similar to DOM event listening, EventEmiter can also remove event binding and use the removeListener (eventName, listener) method to unbind an event. Therefore, the callback function listener must be a naming function, otherwise, the function cannot be found because the function is of the reference type. Even if the function body is the same, it is not the same function, as shown below:
myEmitterIns.on('data',function(e){ console.log(e);});myEmitterIns.removeListener('data',function(e){ console.log(e);});myEmitterIns.emit('data','hello data!');function deal(e){ console.log(e);}myEmitterIns.on('data1',deal);myEmitterIns.removeListener('data1',deal);myEmitterIns.emit('data1','hello data1!');
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
Hello data!
E: \ developmentdocument \ nodejsdemo>
The execution result shows that the data event uses an anonymous function, so it is not removed, and the data1 event is successfully unbound. Note that after emit triggers an event, all callback functions bound to the event will be called, even if you use the removeListener function in a callback function to remove another callback, the subsequent event queue removes the callback. As follows:
Function dealData1 (e) {console. log ('data event executed... a');} myEmitterIns. on ('data', function (e) {console. log (e); myEmitterIns. removeListener ('data', dealData1); // unbind dealData1 here}); myEmitterIns. on ('data', dealData1); myEmitterIns. emit ('data', 'Data event executed... B ');/* The execution result is: The data event is executed... B data event executed... A * // when this event is triggered again, the dealData1 callback has been unbound from myEmitterIns. emit ('data', 'Data event executed... '); // The data event is executed... in addition, you can use removeAllListeners () to remove Event binding.
6. Obtain the number of Event Listeners and listener Functions
Use the emitter. listenerCount (eventName) function to obtain the number of listeners for a specified event. The function emitter. listeners (eventName) can be used to obtain all listening functions for the specified event, as shown below:
Var CBA = () =>{}, cbB = () =>{}; var emitter = new myEmiter (); emitter. on ('data', CBA); emitter. on ('data', cbB); console. log ('data events of the emitter instance are bound with % d callback functions', emitter. listenerCount ('data'); console. log ('they are: ', emitter. listeners ('data '));
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
The data event of the emitter instance is bound with two callback functions.
They are: [[Function: CBA], [Function: cbB]
7. Obtain and set the maximum number of emitter listeners
We recommend that nodejs not listen to more than 10 listeners for the same event. You can view the EventEmitter. defaultMaxListeners attribute to learn about it, as shown below:
Console. log (EventEmitter. defaultMaxListeners); // The result is 10
Emitter uses the getMaxListeners () method to obtain the maximum number of listeners and the setMaxListeners (n) method to set the maximum number of listeners, as shown below:
var cbA = ()=>{}, cbB = ()=>{};var emitter = new myEmiter();emitter.setMaxListeners(1);emitter.on('data',cbA);emitter.on('data',cbB);console.log(emitter.getMaxListeners());
The execution result is as follows:
E: \ developmentdocument \ nodejsdemo> node event-example.js
The maximum number of emitter Event Listeners is: 1
(Node: 6808) Warning: Possible EventEmitter memory leak detected. 2 data listener
S added. Use emitter. setMaxListeners () to increase limit
As shown in the preceding results, if the maximum number of listeners is set, it is recommended that the listening of the same event not exceed the maximum value. Otherwise, memory leakage may be sent.