node.js v0.12.x changes in EventEmitter ruins inheritance - node.js

There is some changes in node.js 0.12.x related to events module.
This changes makes my code that extends EventEmitter class non-workable.
Here is code that works fine in node.js v0.10.35:
teh_emitter.js:
var EventEmitter = require('events');
var util = require('util');
util.inherits(TehEmitter, EventEmitter);
function TehEmitter(){
EventEmitter.call(this);
}
TehEmitter.prototype.on('start', function (fCallback) {
fCallback();
});
module.exports = TehEmitter;
test_teh_emitter.js:
var TehEmitter = require('./teh_emitter');
describe('EventEmitter tests', function(){
describe('#emit() function', function(){
it('should fire start event', function(fCallback){
var oEmitter = new TehEmitter(fCallback);
oEmitter.emit('start', fCallback);
});
})
});
But on node.js v0.12.7 it says:
0 passing (2s)
1 failing
1) EventEmitter tests #emit() function should fire start event:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
I know that in 0.12.x one should assign:
var EventEmitter = require('events');
(though require('events').EventEmitter; should still work for backwards compatability).
But it doesn't helps.
How am I gonna fix this problem?

This was changed in 2c6b424 because of a bug involving event handlers bleeding into all other instances of the same object/"class" (see 7157).
Probably your best bet for compatibility is to just add the event handler in the constructor:
function TehEmitter(){
EventEmitter.call(this);
this.on('start', onStart);
}
function onStart(fCallback) {
fCallback();
}

Related

Trigger function in app.js from module.js

First time poster — please forgive (and call me out) on any formatting mistakes!
So let's say I have app.js, which requires module.js. In module.js I have an express server running that can receive simple webrequests (GET / POST). Is there any way for me to trigger functions in app.js when I receive a request in module.js?
Something along the lines of:
var webModule = require('./module.js')
webModule.on('GET', async function (req) {
//do stuff with the request
});
The reason I'm not just putting the express server in app.js is that I want to run a certain amount of code to verify that the request is legitimate, and then re-use module.js in separate scripts to minimise the amount of code — and avoid having to update 5-6 scripts everytime I want to update the authentication process.
You can use the Event system that exists in Node.js. If you set it up correctly you can emit an event on each call and have a listener respond to the event.
Example from the Node.JS documentation:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
In your case you could create a class that extends EventEmitter that you use in each request. This class can then emit an event when the request gets call which is then handled in your app.js file by setting up the listener.
I might have a solution, will take some time to code (since my question is obviously very simplified).
In module.js:
var functionActions = {};
module.exports = {
on : (async function(requestType, returnFunction){
functionActions[requestType].do = returnFunction;
});
}
//general express code
app.get('*', function(req,res) {
if (verifyRequest(req) == 'okay'){ //authentication
return functionActions['GET'].do();
} else { //if the request is not authorised
res.status(403).send('Stop trying to hack me you stupid hacker ಠ╭╮ಠ');
}
});
I'll try it out and update this answer once I've figured out the potential kinks.

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
});

How I can get timers list in Node JS?

For example I have .js file, it's a single script. I have some functions In this script and this functions are making some timers (setTimeout). All of this timers wasn't associated with the variables.
Like a
function zzz(){
setTimeout(yyy, 100);
};
I need to know when all of this timers will be done, if Node JS has some event for it. Or I need list of all timers in this script, if it exists. To check length of this list in any random moment for example.
You could create an EventEmitter and emit an event at the end of your setTimeout callback. You can then work a solution to track when all of your expected events have fired around this. Extending the example in the docs:
'use strict';
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (data) => {
console.log(data); // yyy
});
function yyy() {
return;
}
setTimeout(() => {
yyy();
myEmitter.emit('event', 'yyy');
}, 100);

How can I use Socket.IO with promises?

As a part of an ongoing effort, I'm changing my current callbacks technique to promises using blue-bird promise library.
I would like to implement this technique with Socket.IO as well.
How can I use Socket.IO with promises instead of callbacks?
Is there any standard way of doing it with Socket.IO? any official solution?
You might look into Q-Connection, which facilitates RPC using promises as proxies for remote objects and can use Socket.IO as a message transport.
Bluebird (and many other promise libraries) provide helper methods to wrap your node style functions to return a promise.
var readFile = Promise.promisify(require("fs").readFile);
readFile("myfile.js", "utf8").then(function(contents){ ... });
https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification
Returns a function that will wrap the given nodeFunction. Instead of
taking a callback, the returned function will return a promise whose
fate is decided by the callback behavior of the given node function.
The node function should conform to node.js convention of accepting a
callback as last argument and calling that callback with error as the
first argument and success value on the second argument.
have a look here https://www.npmjs.com/package/socket.io-rpc
var io = require('socket.io').listen(server);
var Promise = require('bluebird');
var rpc = require('socket.io-rpc');
var rpcMaster = rpc(io, {channelTemplates: true, expressApp: app})
//channelTemplates true is default, though you can change it, I would recommend leaving it to true,
// false is good only when your channels are dynamic so there is no point in caching
.expose('myChannel', {
//plain JS function
getTime: function () {
console.log('Client ID is: ' + this.id);
return new Date();
},
//returns a promise, which when resolved will resolve promise on client-side with the result(with the middle step in JSON over socket.io)
myAsyncTest: function (param) {
var deffered = Promise.defer();
setTimeout(function(){
deffered.resolve("String generated asynchronously serverside with " + param);
},1000);
return deffered.promise;
}
});
io.sockets.on('connection', function (socket) {
rpcMaster.loadClientChannel(socket,'clientChannel').then(function (fns) {
fns.fnOnClient("calling client ").then(function (ret) {
console.log("client returned: " + ret);
});
});
});

Inheriting Node.js' eventemitter fails

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);

Resources