Inheriting Node.js' eventemitter fails - node.js

I'm trying to add the event listener to my class, but it fails, telling me the object has no 'on' method.
Here's the class in its own file:
var events = require('events');
var util = require('util');
var Motion = function Motion (app) {
events.EventEmitter.call(this);
// Load models
app.loadModel('motion', 'motion');
this.on('testevent', function () {
console.log('an event has happened');
});
this.emit('testevent');
}
util.inherits(Motion, events.EventEmitter);
module.exports = Motion;
And here's how I instantiate it:
var Motion = require('./plugins/motion.js');
var motion = new Motion(app);

It looks like you may be asking for the constructor function itself to be an event emitter. Your code makes the objects produced by new with the constructor. i.e., the object motion produced at the end of your snippet should have an on method (as Vadim Baryshev notes, your code should work as you have it if this is the intent, and if that is the case you can ignore the rest of this answer).
If you really want the constructor to emit events, then take a look at this question and the answer I provided to it. However, it's not a great solution, and there appears to be no way of doing it without using the non-standard __proto__.
A better solution is to make a separate event emitter object for the constructor function to use for emissions. As much as I like the constructor-module pattern, it has to be discarded. Many node modules make the module itself the emitter, and have a function exposed by the module as a constructor. For example:
var events = require('events');
var util = require('util');
exports = module.exports = new events.EventEmitter();
exports.Motion = function (app) {
// Load models
app.loadModel('motion', 'motion');
// Emit event
exports.emit('testevent');
};
and to instantiate:
var motion = require('./plugins/motion');
motion.on('testevent', function () {
console.log('an object was constructed');
});
var motionObj = new motion.Motion(app);

Related

Is it possible to implement observer pattern using REST API

I am a newbie to patterns and was wondering whether it is possible to implement observer pattern using REST api. My current view is that it is not possible since REST is more of a pull architecture while observer is more of a push architecture.
Your thoughts are welcome.
An object maintains a list of dependents/observers and notifies them automatically on state changes. To implement the observer pattern, EventEmitter comes to the rescue
// MyFancyObservable.js
var util = require('util');
var EventEmitter = require('events').EventEmitter;
function MyFancyObservable() {
EventEmitter.call(this);
}
util.inherits(MyFancyObservable, EventEmitter);
This is it; we just made an observable object! To make it useful, let's add some functionality to it.
MyFancyObservable.prototype.hello = function (name) {
this.emit('hello', name);
};
Great, now our observable can emit event - let's try it out!
var MyFancyObservable = require('MyFancyObservable');
var observable = new MyFancyObservable();
observable.on('hello', function (name) {
console.log(name);
});
observable.hello('john');
for more details follow the link
Fundamental Node.js Design Patterns
Immediate State Updates for REST/HTTP APIs using Observer Pattern

access data from this nodeJS function

I want to use "data" outside of this function. Please can some one show me how?
resemble('/Users/User/Documents/dev/engineerappcopy/VGimages/'+deviceName+'.png')
.compareTo('/Users/User/Documents/dev/engineerappcopy/VGimages/'+"nexUpdate"+'.png')
.ignoreColors().onComplete(function(data) {
browser.sleep(5000)
console.log(data);
data.getDiffImage().pack().
pipe(fs.createWriteStream('/Users/User/Documents/dev/engineerappcopy/VGimages/'+deviceName+'VG.png'));
});
I am aware that this is asynchronous, however I am struggling with this.
I would suggest you to use EventEmitters. You can use this if at all you want to indicate if any action is finished and optionally you can pass the data as well.
Create a new javscript file 'my-emitter.js'
my-emitter.js (ES6 version)
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
module.exports = myEmitter;
OR
my-emitter.js (Javascript version)
var EventEmitter = require('events').EventEmitter;
var util = require('util');
function MyEmitter(){
EventEmitter.call(this);
}
util.inherits(MyEmitter,EventEmitter);
myEmitter = new MyEmitter();
module.exports = myEmitter;
Your code snippet:
(Check the comments in the code). Emit an event saying that data is available after the async operation is complete
myEmitter.emit('img-op-complete',data);
var myEmitter = require('./my-emitter.js'); //Get your emitter from the module
resemble('/Users/User/Documents/dev/engineerappcopy/VGimages/'+deviceName+'.png')
.compareTo('/Users/User/Documents/dev/engineerappcopy/VGimages/'+"nexUpdate"+'.png')
.ignoreColors().onComplete(function(data) {
browser.sleep(5000)
//Emit the event that data is available and pass the data
myEmitter.emit('img-op-complete',data);
console.log(data);
data.getDiffImage().pack().
pipe(fs.createWriteStream('/Users/User/Documents/dev/engineerappcopy/VGimages/'+deviceName+'VG.png'));
});
othermodule.js
Where ever you want the data (if in other module), use the below piece of code
var myEmitter = require('./my-emitter.js'); //Get your emitter from the module
myEmitter.on('img-op-complete', function(data){
console.log(data); //You'll get your data here after op is done
})
Fore more info on events, https://nodejs.org/dist/latest-v6.x/docs/api/events.html
NOTE:
Promises is also nice solution, but if you use promises good design if data is needed within the same module. But events present a good design pattern in node.js
I would suggest go with promises, you would be able to use this promise across module also if you export it.
There are some really nice articles about how to use promises like Promise.
Coming to how to approach the above issue via promises,
function foo(){
return new Promise(function(resolve,reject){
resemble(<yourPath>)
.compareTo(<yourPath>)
.ignoreColors().onComplete(function(data) {
//for best practice do handle errors
if(err<anyError>){
reject(err);
} else{
resolve(data);
}
});
})
}
Now You can use the above promise where you want to use the data variable :
foo().then(function(<data>){
//do whatever you wish to do with the data
}).catch(function(<err>){
//handle the error
});

Continuous tasks in nodejs

i'am using nodejs with express for my webapp and i need to to run continuously
some code which checks if some data change and then update my mongodb.
How can i easily create a background process which runs the whole time together with the main task? So that the background task/process can inform the main task.
What i have tried already:
to solve this problem with a "setInterval" Function in the main process --> I works with no problem but think its not a good idea because it blocks the node event loop
Use child processes -> i could not found a good tutorial on them --> is there a easier method, perhaps a library which could help me?
some background worker libraries -->But do heavy-load tasks on the a child-process and finish but i need to do the work all the time
Update:
Final Solution:
UpdateEvent.js:
var events = require('events');
function Updater(time) {
this.time = time;
this.array = [
{number: 1},
{number: 2}
];
var that;
events.EventEmitter.call(this);
this.init = function()
{
that = this;
console.log("Contructor");
//Start interval
setInterval(that.run,that.time);
};
this.run = function()
{
that.array.forEach(function (item) {
if(item.number === 2)
{
that.emit('Event');
}
});
};
}
Updater.prototype.__proto__ = events.EventEmitter.prototype;
module.exports = Updater;
and then the code that uses it:
server.js:
var Updater = require('./UpdaterEvent');
var u = new Updater(10000);
u.init();
u.on('Event',function () {
console.log("Event catched!");
});
I followed the tutorial at:
http://www.sitepoint.com/nodejs-events-and-eventemitter/
The problem is the way you export your Updater constructor function:
exports.Updater = Updater;
When you require it, you do
var Updater = require('./UpdaterEvent');
and then try to run:
var u = new Updater(10000);
The problem is that you do not expose the function itself, but an object with a property called Updater which contains the function. Hence you either have to export it using
module.exports = Updater;
or you have to require it using:
var Updater = require('./UpdaterEvent').Updater;
Either way, then calling new Updater() will work. At the moment, you try to initialize a new object by calling an object instead of a constructor function, hence the error message:
TypeError: object is not a function
You should look into Events and EventEmitter
You could use child-process you don't really need to since JS is asynchronous. Just create a function for your background process and pass it your eventEmitter object. You can use setInterval or a while(true) loop to continuously check for the data change. When the data changes, call eventEmitter.emit('someEvent'); which will trigger a function in your main task to update your mongoDB.

Node.js delegating functions to an imported module

Currently I have a Node.js module with the following form :
var events = require('events');
var emitter = new events.EventEmitter();
function emitSomething() {
emitter.emit("event");
}
exports.emitSomething = emitSomething;
exports.on = emitter.on;
However any callback registered through on do not get called when I call emitSomething.
I can get around this by changing the last line to
exports.on = function(event, callback) { emitter.on(event, callback); };
Is there a reason I can't delegate the on function to a function defined in another module?
This is a common JS mistake. Note that the on method depends on this (which is emitter in your example). However, all you export is the function itself, so it's context (emitter) is lost when you call it later.
Here is a small example for this issue:
var someObj = {
doSth: function() { console.log(this) }
};
someObj.doSth(); // "Object { ..."
var doSth = someObj.doSth;
doSth(); // "Window { ..."
When I call doSth as method of someObj, this references someObj as expected. After I copied the function to doSth, this references it's new context, in the browser the global context Window. This is what happens in your case.
As you already mentioned, you have to bind the emitter context to the function. This can also be done like this:
exports.on = emitter.on.bind(emitter);

node.js EventEmitter causes scope problems

When using nodejs event system, I met with an annoying problem. As the code below shows, when a listener catch a event, the event emitter object owns 'this' in the callback function instead of the listener.
It's not a big problem if you put the callback in the listener's constructor, because besides pointer 'this', you can still use other variables defined in the constructor's scope, like the 'self' or 'that' way.
But, if the callback is put outside the constructor like the prototype methods, it appears to me that there is no ways to get the listener's 'this'.
Not very sure if there are any other solutions. And also, a little confused about why nodejs event emit use the emitter as the caller install of the listener?
util = require('util');
EventEmitter = require('events').EventEmitter;
var listener = function () {
var pub = new publisher();
var self = this;
pub.on('ok', function () {
console.log('by listener constructor this: ', this instanceof listener);
// output: by listener constructor this: false
console.log('by listener constructor self: ', self instanceof listener);
// output: by listener constructor this: true
})
pub.on('ok', this.outside);
}
listener.prototype.outside = function () {
console.log('by prototype listener this: ', this instanceof listener);
// output: by prototype listener this: false
// how to access to listener's this here?
}
var publisher = function () {
var self = this;
process.nextTick(function () {
self.emit('ok');
})
}
util.inherits(publisher, EventEmitter);
var l = new listener();
Try binding the listener explicitly to the callback:
pub.on('ok', this.outside.bind(this));

Resources