Trigger function in app.js from module.js - node.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.

Related

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

Scaffolding a Node.js app properly without Express (the app doesn't receive requests)

[This question is quite vague, I apologize for it. I'm trying to address my various troubles by answering the question myself]
I am building a Node.js app which has to perform various tasks at given intervals. Here is the global scaffold (involves bluebird promises and mongoose for DB interactions) :
var Promise = require("bluebird");
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
// Personal modules
var bootApp = require(...);
var doStuffA = require(...);
var doStuffB = require(...);
var doStuffC = require(...);
// running locally, but meant to be deployed at some point
mongoose.connect('mongodb://localhost:27017/myDatabase');
var db = mongoose.connection;
db.on('error', () => {
console.log("Error : lost connection !"));
process.exit(1);
});
db.once('open', () => {
bootApp() // always start by booting
.then( () => { // then start the infinite loop of events
setInterval(doStuffA, 1000*60*60); // 1x/1h
setInterval(doStuffB, 1000*60*10); // 1x/10min
setInterval(doStuffC, 1000*60*3); // 1x/3min
}).catch((e) => { // errors are handled by doStuffX(), so we should never catch anything here
console.log(e.message);
process.exit(1);
});
});
Each module doStuffX is a function returning a Promise, handling its own errors, and should finish at some point.
Expected behaviour for the entire app :
The app should be able to run forever
The app should try to doStuffX() at the given interval, regardless of whether it succeeded or failed last time.
[Optional :] The app should close smoothly without retrying any doStuff upon receiving a "shut down" signal.
My question : how to build a clean scaffold for such an app ? Can I get rid of setInterval and use promises instead ? One of my main concerns is to make sure the previous instance of doStuffX() is finished before starting the next one, even if it involves "killing" it in some way.
I am open to any link about scaffolding apps, but PLEASE DO NOT GIVE ME AN ANSWER/LINK INVOLVING EXPRESS : I don't need Express, since my app doesn't receive any request. (everything I found so far starts with Express :/)
If you don't want to start the next doStuffX() until the previous one is done, then you can replace your setInterval() with repeated setTimeout() calls.
function runA() {
setTimeout(function() {
doStuffA().then(runA).catch(function(err) {
// decide what to do differently if doStuffA has an error
});
}, 1000*60*60);
}
runA();
You could also add a timeout to this so that if doStuffA() doesn't respond within a certain amount of time, then you take some other action. This would involve using another timer and a timeout flag.
[I answer my own question, trying to put here everything I changed afterwards, in case someone falls into this page someday...]
For the Mongoose part of the scaffold, here is what I got so far for a reliable long-term DB connection :
The Mongoose documentation gives a fancy way to ensure the driver will never give up on trying to reconnect with reconnectTries
I don't really understand socketOptions and keepalive which seem related to replicas, so I leave them out of my code for now
Since Mongoose should autoreconnect whenever something goes wrong, I'll keep the db.once('open') as the access to the app code itself, even though I don't really understand yet the difference with db.on('connected')
I recommend reading this.
var Promise = require("bluebird");
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
// Personal modules
var bootApp = require(...);
var doStuffA = require(...);
var doStuffB = require(...);
var doStuffC = require(...);
// running locally, but meant to be deployed at some point
var uri = 'mongodb://localhost:27017/myDatabase';
// the added option makes sure the app will always try to reconnect...
mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } });
var db = mongoose.connection;
db.on('error', () => {
console.log("Error with Mongoose connection."));
});
db.once('open', () => {
bootApp() // always start by booting
.then( () => { // then start the infinite loop of events
//////////////////////////////////
/// Here goes the actual stuff ///
//////////////////////////////////
}).catch((e) => { // errors are handled by doStuffX(), so we should never catch anything here
console.log(e.message);
});
});
Now, for the actual repetitive stuff, my objective is to make sure everything runs smoothly, and that no process gets stuck. About the changes I made :
The methods used are not native ES6 but are specific to bluebird. You can read about .timeout() and .delay() which I find very useful for chaining timeouts and intervals in a clean code.
In my mind, .then(runA, runA) should always launch ONE UNIQUE instance of runA but I'm concerned about whether I could actually end up launching two parallel instances...
// Instead of using setInterval in a bluebird promised environment...
setInterval(doStuffA, 1000*60*60); // 1x/1h
// I would have liked a full promise chain, but as jfriend00 stated,
// It will end up crashing because the initial promise is never resolved...
function runA() {
return doStuffA()
.timeout(1000*60*30) // kill the running instance if it takes longer than 30min
.delay(1000*60*60) // wait 60min
.then(runA, runA); // whatever the outcome, restart the process
}
runA();
// Therefore, a solution like jfriend00's seems like the way to go :
function runA() {
setTimeout(function() {
doStuffA()
.timeout(1000*60*30)
.then(runA, runA)
}, 1000*60*60);
}
runA();

How to test error in request with Nock?

I want to test the error in a request return. I'm using nock in my tests, how can I force Nock to provoke an error? I want to achieve 100% test coverage and need to test err branch for that
request('/foo', function(err, res) {
if(err) console.log('boom!');
});
Never enter in the if err branch. Even if hit err is a valid response, my Nock line in test looks like this
nock('http://localhost:3000').get('/foo').reply(400);
edit:
thanks to some comments:
I'm trying to mock an error in the request. From node manual:
https://nodejs.org/api/http.html#http_http_request_options_callback
If any error is encountered during the request (be that with DNS resolution, TCP level errors, or actual HTTP parse errors) an 'error' event is emitted on the returned request object
An error code (e.g. 4xx) doesn't define the err variable. I'm trying to mock exactly that, whatever error that defines the err variable and evaluates to true
Use replyWithError.
From the docs:
nock('http://www.google.com')
.get('/cat-poems')
.replyWithError('something awful happened');
When you initialise a http(s) request with request(url, callback), it returns an event emitter instance (along with some custom properties/methods).
As long as you can get your hands on this object (this might require some refactoring or perhaps it might not even be suitable for you) you can make this emitter to emit an error event, thus firing your callback with err being the error you emitted.
The following code snippet demonstrates this.
'use strict';
// Just importing the module
var request = require('request')
// google is now an event emitter that we can emit from!
, google = request('http://google.com', function (err, res) {
console.log(err) // Guess what this will be...?
})
// In the next tick, make the emitter emit an error event
// which will trigger the above callback with err being
// our Error object.
process.nextTick(function () {
google.emit('error', new Error('test'))
})
EDIT
The problem with this approach is that it, in most situations, requires a bit of refactoring. An alternative approach exploits the fact that Node's native modules are cached and reused across the whole application, thus we can modify the http module and Request will see our modifications. The trick is in monkey-patching the http.request() method and injecting our own bit of logic into it.
The following code snippet demonstrates this.
'use strict';
// Just importing the module
var request = require('request')
, http = require('http')
, httpRequest = http.request
// Monkey-patch the http.request method with
// our implementation
http.request = function (opts, cb) {
console.log('ping');
// Call the original implementation of http.request()
var req = httpRequest(opts, cb)
// In next tick, simulate an error in the http module
process.nextTick(function () {
req.emit('error', new Error('you shall not pass!'))
// Prevent Request from waiting for
// this request to finish
req.removeAllListeners('response')
// Properly close the current request
req.end()
})
// We must return this value to keep it
// consistent with original implementation
return req
}
request('http://google.com', function (err) {
console.log(err) // Guess what this will be...?
})
I suspect that Nock does something similar (replacing methods on the http module) so I recommend that you apply this monkey-patch after you have required (and perhaps also configured?) Nock.
Note that it will be your task to make sure you emit the error only when the correct URL is requested (inspecting the opts object) and to restore the original http.request() implementation so that future tests are not affected by your changes.
Posting an updated answer for using nock with request-promise.
Let's assume that your code calls request-promise like this:
require('request-promise')
.get({
url: 'https://google.com/'
})
.catch(res => {
console.error(res);
});
you can set up nock like this to simulate a 500 error:
nock('https://google.com')
.get('/')
.reply(500, 'FAILED!');
Your catch block would log a StatusCodeError object:
{
name: 'StatusCodeError',
statusCode: 500,
message: '500 - "FAILED!"',
error: 'FAILED!',
options: {...},
response: {
body: 'FAILED!',
...
}
}
Your test can then validate that error object.
Looks like you're looking for an exception on a nock request, this maybe can help you:
var nock = require('nock');
var google = nock('http://google.com')
.get('/')
.reply(200, 'Hello from Google!');
try{
google.done();
}
catch (e) {
console.log('boom! -> ' + e); // pass exception object to error handler
}

Events or functions on javascript class

I'm using EventEmitter in some classes, but i'm really confused whether event listening and events emitting are more efficient than calling object methods?
I want the object to be able to listen for a number of events that are emitted to it, and also emit a number of events to the object that originally emitted the events to the object and some others objects as well.
And i pretty much confused whether when should i use functions which in turn call other object methods and so on.
Events improve module decoupling. It is all about this simple question: "How many files do I have to touch to modify or add feature X?"
A simple example: You have a web server, a logging module and a starting script, which ties both together on startup. The function call way looks like this:
// Startup.js
var Startup = function() {
var logger = new Logger();
var server = new Server(logger);
};
// Logger.js
var Logger = function() {
};
Logger.prototype.log = function(msg) {
console.log(msg);
};
// Server.js
var Server = function(logger) {
this.logger = logger;
};
Server.prototype.start() {
this.logger.log("Start server...");
};
You can see that Startup knows all classes and Server knows about logger and how to use it. If I want to rename Logger's function log to write I have to touch Logger and Server.
Now let's have a look at a event driven approach:
// Startup.js
var Startup = function() {
var logger = new Logger();
var server = new Server();
server.addListener(logger);
};
// Logger.js
var Logger = function() {
this.on("startup", function(msg) {
console.log(msg);
});
};
Logger.prototype.__proto__ = EventEmitter.prototype;
// Server.js
var Server = function() {
};
Server.prototype.start() {
this.emit("startup", "Start server...");
};
Server.prototype.__proto__ = EventEmitter.prototype;
Now Logger and Server don't know each other. I can rename log and all I have to touch is Logger.js. I can even remove Logger or add more Loggers, all of them working with Server. But I never have to touch Server.js.
This is a simple example and decoupling doen't look important here. But the larger a project gets, the more benefits come up.
You can Unit-Test Server without having to mock Logger. And Logger is only one dependency. Imagine the advantage if Server had five or more submodules you have to simulate.
I hope this helps you to understand the benefits of event driven architectures.

Custom Events in Node.js with Express framework

So, I'd like to know how to create custom events in node.js, and I'm hitting a wall. I'm pretty sure I'm misunderstanding something about how express works and how node.js events work.
https://creativespace.nodejitsu.com That's the app.
When a user creates a new "activity" (something that will happen many times) they send a POST request. Then within my route, if that POST succeeds I'd like to emit an event, that tells socket.io to create a new namespace for that activity.
In my route file:
var eventEmitter = require('events').EventEmitter;
// Tell socket.io about the new space.
eventEmitter.emit('new activity', {activityId: body.id});
And socket.io:
// When someone creates a new activity
eventEmitter.on('new activity', function (data) { // this gives and error
var newActivity = '/activity?' + data.activityId;
io.of(newActivity).on('connection', function (socket) {
// Socket.io code for an activity
});
});
So the error I get is CANNOT CALL METHOD ON OF UNDEFINED and it refers to what would be line 2 in the socket.io above. I think I'm messing up my requires, maybe...or I'm not quite understanding how events work.
Any help, even a reference to good reading on Node.js events would rock!
Thanks!!!
If using express you can also just listen for event on the express 'app' which inherits from EventEmitter. For example:
res.app.on("myEvent", function)
and emit to it like
res.app.emit("myEvent", data)
You should treat EventEmitter as a class you can inherit from. Try this:
function MyEmitter () {
events.EventEmitter.call(this);
}
util.inherits(MyEmitter, events.EventEmitter);
Now you can use your class to listen and emit events:
var e = new MyEmitter;
e.on("test", function (m) { console.log(m); });
e.emit("test", "Hello World!");

Resources