Events : Event emitter
Events module provides the current task event-driven programming where objects (called "emitters") periodically emit named events.
The Events module is a typical subscription and publish event driven model. If you are familiar with the traditional JavaScript asynchronous development model, then the JSRE synchronous module can use the Events module for asynchronous conversion.
User can use the following code to import the Events
module.
var EventEmitter = require('events');
Or:
var EventEmitter = require('events').EventEmitter;
Example
#!/bin/javascript
var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('message', (msg) => {
console.log('onmessage:', msg);
});
while (true) {
emitter.emit('message', 'Test!');
sys.sleep(1000);
}
Run the code will print the following information:
[JSRE-USR]onmessage: Test!
[JSRE-USR]onmessage: Test!
[JSRE-USR]onmessage: Test!
[JSRE-USR]onmessage: Test!
...
Support
The following shows Events
module APIs available for each permissions.
User Mode | Privilege Mode | |
---|---|---|
EventEmitter | ● | ● |
EventEmitter.inherits | ● | ● |
emitter.addListener | ● | ● |
emitter.on | ● | ● |
emitter.off | ● | ● |
emitter.emit | ● | ● |
emitter.once | ● | ● |
emitter.removeListener | ● | ● |
emitter.removeAllListeners | ● | ● |
emitter.eventNames | ● | ● |
emitter.listeners | ● | ● |
emitter.listenerCount | ● | ● |
EventEmitter Class
The EventEmitter plays a role as base class for "emitters". User application would not directly creates an instance of EventEmitter since EventEmitter is an abstract trait which defines its behavior and grants to sub-classes.
new EventEmitter()
- Returns: {EventEmitter} A new emitter.
Returns with a new EventEmitter object.
Example
var emitter = new EventEmitter();
EventEmitter.inherits(obj)
obj
{Object} Target object.
Make target object inherit Emitter properties and methods.
Example
var anyObject = new XXX();
EventEmitter.inherits(anyObject);
anyObject.on('event', () => {
console.log('on event!');
});
Emitter Object
emitter.addListener(event, listener)
event
{String} | {Array} The name or names of the event.listener
{Function} The callback function.- Returns: {Emitter} This emitter.
It is an alias for emitter.on(eventName, listener)
.
Adds the listener
callback function to the end of the listener's list for the given event
. No checks are made to see if the listener
has already been added. In case of multiple calls the listener
will be added and called multiple times.
Example
var emitter = new EventEmitter();
var eventSequence = '';
var listener1 = function() {
eventSequence += '2';
};
emitter.addListener('test', listener1);
emitter.addListener('test', listener1);
emitter.emit('test');
console.log(eventSequence); // prints '22'
- Listen to multiple events at once:
var emitter = new EventEmitter();
function callback(error) {
if (error) {
console.log(error.message);
} else {
console.log('OK!');
}
}
emitter.on(['error', 'ok'], callback);
emitter.emit('ok');
emitter.emit('error', new Error('Test error'));
emitter.on(event, listener)
event
{String} | {Array} The name or names of the event.listener
{Function} The callback function.- Returns: {Emitter} This emitter.
Adds the listener
callback function to the end of the listener's list for the given event
. No checks are made to see if the listener
has already been added. In case of multiple calls the listener
will be added and called multiple times.
Example
var emitter = new EventEmitter();
emitter.on('event', function() {
console.log('emit event');
});
emitter.emit('event');
emitter.off(event, listener)
event
{String} The name of the event.listener
{Function} The callback function.- Returns: {Emitter} This emitter.
Removes listener
from the list of event listeners. Alias of emitter.removeListener()
.
emitter.emit(event[, ...arg])
event
{String} The name of the event....args
{Any} Optional arguments. default: undefined.- Returns: {Boolean} Returns true if the event had listeners, false otherwise.
Synchronously calls each of the listeners registered for the event, in the order they were registered, passing the supplied arguments to each.
Example
var emitter = new EventEmitter();
emitter.addListener('event', function() {
console.log('emit event');
});
emitter.emit('event'); // true
emitter.emit('not_an_event'); // false
emitter.once(event, listener)
event
{String} The name of the event.listener
{Function} The callback function.- Returns: {Emitter} This emitter.
Adds the listener
as a one time listener for the event
.
Using this method, it is possible to register a listener that is called at most once for a particular event
. The listener will be invoked only once, when the first event
is emitted.
Example
var emitter = new EventEmitter();
var onceCnt = 0;
emitter.once('once', function() {
onceCnt += 1;
});
emitter.emit('once');
emitter.emit('once');
// onceCnt === 1
emitter.removeListener(event, listener)
event
{String} The name of the event.listener
{Function} The callback function.- Returns: {Emitter} This emitter.
Removes listener
from the list of event listeners.
If you add the same listener
multiple times, this removes only one instance of them.
Example
var emitter = new EventEmitter();
var listener = function() {
console.log('listener');
};
emitter.addListener('event', listener);
emitter.removeListener('event', listener);
emitter.removeAllListeners([event])
event
{String} The name of the event. default: all events.- Returns: {Emitter} This emitter.
Removes all listeners.
If event
was specified, it only removes the listeners for that event.
Example
var emitter = new EventEmitter();
function removableListener() {
console.log("listener called");
}
emitter.addListener('event1', removableListener);
emitter.addListener('event2', removableListener);
emitter.addListener('event2', removableListener);
emitter.addListener('event3', removableListener);
emitter.removeAllListeners('event2');
var res = emitter.emit('event2'); // res == false
res = emitter.emit('event1'); // res == true, prints "listener called"
emitter.removeAllListeners();
res = emitter.emit('event1'); // res == false
res = emitter.emit('event3'); // res == false
emitter.eventNames()
- Returns: {Array} An array of all listened events.
Get all listened events.
Example
var emitter = new EventEmitter();
emitter.on('a', () => {});
emitter.on('b', () => {});
console.log(emitter.eventNames());
// ['a', 'b']
emitter.listeners(event)
event
{String} The name of the event.- Returns: {Array} An array of all listened functions on this event.
Returns a copy of the listener array for the event named event
.
Example
var emitter = new EventEmitter();
emitter.on('a', () => {});
emitter.on('a', () => {});
var funcs = emitter.listeners('a');
emitter.listenerCount(event)
event
{String} The name of the event.- Returns: {Integer} Number of all listened functions on this event.
Returns the number of listeners for the event named event
.
Example
var emitter = new EventEmitter();
emitter.on('a', () => {});
emitter.on('a', () => {});
var count = emitter.listenerCount('a');
// 2
Catch Promise Rejection
Using async
functions with event handlers is problematic, because it can lead to an unhandled rejection in case of a thrown exception:
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});
The captureRejections
option in the EventEmitter
constructor or the global setting change this behavior, installing a .then(undefined, handler)
handler on the Promise
. This handler routes the exception asynchronously to the Symbol.for('jsre.rejection')
method if there is one, or to 'error'
event handler if there is none.
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('jsre.rejection')] = console.log;
Setting events.captureRejections = true
will change the default for all new instances of EventEmitter
.
const events = require('events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
The 'error'
events that are generated by the captureRejections
behavior do not have a catch handler to avoid infinite error loops: the recommendation is to not use async
functions as 'error'
event handlers.
Emitter Special Event
newListener
event
{String} The name of the event.listener
{Function} The event handler function.
The EventEmitter
instance will emit its own 'newListener'
event before a listener is added to its internal array of listeners.
Example
var emitter = new EventEmitter();
// Only do this once so we don't loop forever
emitter.once('newListener', function(event, listener) {
if (event === 'event') {
// Insert a new listener in front
emitter.on('event', function() {
console.log('B');
});
}
});
emitter.on('event', function() {
console.log('A');
});
emitter.emit('event');
// Print:
// B
// A
removeListener
event
{String} The name of the event.listener
{Function} The event handler function.
The 'removeListener'
event is emitted after the listener is removed.
Synchronous to asynchronous
JSRE provides a synchronous multitasking model. Like other language environments, it also provides an asynchronous processing model. You can choose any way to develop application, even in one application, depending on the characteristics of the different transactions, you can using different methods at one application.
If you are very familiar with asynchronous development, the following method here can convert synchronization to asynchronous.
Task Message
Example
var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('event1', (msg) => {
console.log('event1 on:', msg);
});
emitter.on('event2', (msg) => {
console.log('event1 on:', msg);
});
emitter.on('event3', (msg) => {
console.log('event1 on:', msg);
});
Task.async(false);
while (true) {
var msg = Task.recv();
if (msg) {
emitter.emit(msg.event, msg);
}
}
CAN-Bus
Example
var EventEmitter = require('events');
var Canbus = require('canbus');
var canbus = Canbus.open(0);
// We can use inheritance mode.
EventEmitter.inherits(canbus);
canbus.setMode('peli');
canbus.start();
canbus.on('message', (frame) => {
console.log('receive:', frame);
});
canbus.on('error', () => {
console.log('CAN-Bus error:', canbus.state);
canbus.reset();
canbus.start();
});
while (true) {
var frame = Canbus.canFrame();
var result = canbus.read(frame);
if (result > 0) {
canbus.emit('message', frame);
} else if (result < 0) {
canbus.emit('error');
}
}
iosched
Example
var EventEmitter = require('events');
var Canbus = require('canbus');
var iosched = require('iosched');
var canbus = Canbus.open(0);
// We can use inheritance mode.
EventEmitter.inherits(canbus);
var ioevent = iosched.event(iosched.READ, canbus.fd(),
() => {
var frame = Canbus.canFrame();
var result = canbus.read(frame);
if (result > 0) {
canbus.emit('message', frame);
} else if (result < 0) {
console.log('CAN-Bus error:', canbus.state);
canbus.reset();
canbus.start();
}
return true; // do not remove from iosched list.
});
canbus.setMode('peli');
canbus.start();
canbus.on('message', (frame) => {
console.log('receive:', frame);
});
iosched.add(ioevent);
while (true) {
iosched.poll();
}