Can I know if a javascript file has been executed? - javascript

I am using a express framework on node and I want to change the value(increase or decrease) of a variable in my testing module each time the module is run. Is there a way to know if the file has been executed and keep it in memory so that next time the file is run again, the value changes again? I want to increase the variableToChange each time the module is executed.
Here is my code:
'use strict';
var util = require('util');
var makeApiCall = require('proc-utils').makeApiCall;
var baseUrl = 'http://localhost:' + (require('../../config').port || 3000);
var url = {
endpoint: '/patients/register',
method: 'post'
};
var ct = {
test: function (data, cb) {
var options = {
type: 'form',
data: data,
baseUrl: baseUrl
};
makeApiCall(url.endpoint, url.method, options, cb);
}
};
module.exports = ct;
//-- Test Code ----------------------------------------------------------
var variableToChange=0;
if (require.main === module) {
(function () {
var data = {
first_name:'John',
last_name:'Doe',
email:'shnsdfn'+variableToChange+'b#sh.com',
password:'John1234'
};
ct.test(data, console.log);
})();
}

One solution is storing the information you need in the cookie session:
var cookieParser = require('cookie-parser');
var session = require('express-session');
express().use(cookieParser()) // include the cookies middleware to parse and manage sessions
.use(session({secret : 'mysecret'}))//set up the session with minimal config (secret)
.use(function(req,res,next){
req.session.variableToSave = 0; // initialize variable you want to save
next(); // starts next middleware
});
But this is for storing informations for browser that connects to the server.
Other Solution is maintaining the log file by appending the desired values with other relevant informations to it.

Check app.locals in Express API reference: http://expressjs.com/api.html#app.locals

Related

How to create a reusable Socket.IO module

I have troubles for creating a module which exposes functionalities for my Socket.IO library:
const sio = require('socket.io');
module.exports = function(server) {
const io = sio(server);
return {
register: function(namespace) {
let nsp = io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
The problem is now how do I make use of this in other modules? In my app.js
I create the server with Express and can instantiate the module with require('./mysocketio')(server) but not in other modules because server is not available there. What's a nice way to resolve these circular dependencies?
Well you can achieve those in various ways, like:
setting objects to global namespace. (altering global needs care)
Use module.exports and require the object in the other files. (can lead to circular dependency issues if not done properly)
pass the instance as arguments to the controllers, while requiring them in routes.
myModule.js Module which exposes functionalities of your Socket.IO library
const sio = require('socket.io');
module.exports = function(server) {
const io = sio(server);
return {
register: function(namespace) {
let nsp = io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
FLow 1: set the module in global namespace.
app.js
var app = require('express').createServer();
var io = require('./myModule')(app);
global._io = io;
app.listen(80)
controller.js
module.exports = function(io){
var that={};
/*
* Private local variable
* made const so that
* one does not alter it by mistake
* later on.
*/
const _io = global._io;
that.myAction = function(req,res){
_io.register('newRoom');
res.send('Done');
}
return that;
}
Flow 2: passing module as arguments.
app.js
var app = require('express').createServer();
var io = require('./myModule')(app);
require(./router.js)(app,io);
app.listen(80);
router.js
/*
* Contains the routing logic
*/
module.exports = function (app,io) {
//passing while creating the instance of controller for the first time.
var controller = require("./controller")(io);
app.get('/test/about',controller.myAction);
};
controller.js
module.exports = function(io){
var that={};
const _io = io;
that.myAction = function(req,res){
_io.register('newsRoom');
res.send('Done');
}
// everything attached to that will be exposed
// more like making public member functions and properties.
return that;
}
Flow 3: Setting io to global. Thus no need to pass server every time.
app.js
var app = require('express').createServer();
require('./myModule')(app);
require(./router.js)(app);
app.listen(80);
controller.js
// no need to pass the server as io is already initialized
const _io = require('./myModule')();
module.exports = function(io){
var that={};
that.myAction = function(req,res){
_io.register('newsRoom');
res.send('Done');
}
return that;
}
myModule.js
module.exports = function( server ) {
const _io = global._io || require('socket.io')(server);
if(global._io === undefined){
//initializing io for future use
global._io = _io;
}
return {
register: function(namespace) {
let nsp = _io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
Probably, the cleanest way is to pass is as arguments to the controllers, while requiring them in routes. Although 3rd flow seems promising but one should be care full while altering the global namespace.
It's not really a circular dependency; It's just that your module a) depends on another module that's not globally available and b) your module is presumably used in many places in your code.
Global
A possible solution (with downsides), is to just load your module once, and attach it to a global:
global.mysocketio = require('./mysocketio')(server);
This allows you to access global.mysocketio anywhere in your project, once it has been loaded. This is a construction that I personally use for an own logger construction; My logger is used in many places around my code, so I just keep it attached to global.log.
However, usage of globals is a bit dirty; It gives problems with namespace-separation (what is somewhere some code decides to use global.mysocketio itself), and it creates an 'invisible' dependency; Other code just assumes that a certain global will exist, and it's not that easy to find these dependencies.
Export
A nicer solution is to just pass the variable wherever needed. There are many ways to do this. I understand that your app.js doesn't have the server variable available, but it surely is including your express-code in some way. If you need the 'server' or 'mysocketio' available from app.js, just export it from your module where you are creating 'server'. Like:
module.exports.expressServerVar = server;
Just my 2 cents; Do you strongly disagree with me or am I missing something important? Let me know!
I'd use a factory or dependency injection. You could use something like jimple.
But here's an example without using any external dependencies. This is by no means the best code example but it should hopefully get the point across. I'd still recommend using jimple rather than this.
// app.js
var express = require('express');
var app = express();
var factory = require('./factory.js');
factory.setExpress(app); // This could also be done in the factory constructor. Or you could instanciate your express app in the factory.js class.
// factory.js
var socketIoModule = require('./your-socket-io-module.js')
function Factory() {
}
Factory.prototype.setExpress = function(app) {
this.app = app;
}
Factory.prototype.getSocketIOModule = function() {
return socketIoModule(this.app);
}
// By exporting it this way we are making it a singleton
// This means that each module that requires this file will
// get the same instance of factory.
module.exports = new Factory();
// some code that needs socket io module
var factory = require('./factory.js');
function() {
var socketIo = factory.getSocketIOModule();
socketIo.doStuff();
}
Approach that I use in my applications is exposing server and io instances from start script and reusing them in modules
// Setup servers.
var http = require('http').Server(app);
var io = require('socket.io')(http);
// Setup application.
require('./server/app')(app, express, io);
// Start listening on port.
http.listen(configs.PORT, function() {
console.log("Listening on " + configs.PORT);
});
Inside your modules you can use io instance to setup event handlers or emit events, something like this
module.exports = {
contest: function(io, contest) {
var namespace = io.of('/' + contest.id);
namespace.on('connection', function(socket) {
socket.on('word', function(data) {
...
});
});
}
};
For your sample
I would put this part in app.js or in js file that is used to start server
const sio = require('socket.io');
const io = sio(server);
and will have Socket.IO module like this
module.exports = function(server, io) {
return {
register: function(namespace) {
let nsp = io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
My sample
https://github.com/gevorg/typeitquick/blob/master/web.js
https://github.com/gevorg/typeitquick/blob/master/server/contest.coffee
https://github.com/gevorg/typeitquick/blob/master/server/io.coffee

File with variable that gets updated, and other files see that change?

I'm trying to build a simple tool that pings a bunch of url's to monitor their status and it updates a variable with each app's status.
I also have another file which i'd like to be able to execute at any time to get the current status of each app from that variable.
Here's my main file and you can see there are 2 exports - start, and getStatuses.
index.js
'use strict';
const rest = require('restler');
const time = require('simple-time');
const seconds = time.SECOND;
// The list of apps to check if are running
var apps = {
myApp: {
url: 'http://myUrl.com',
status: null,
lastUpdatedAt: new Date()
}
};
/**
* Loop through and check the status of every app
*/
function checkAllStatuses() {
for (var name in apps) {
if (apps.hasOwnProperty(name)) {
var app = apps[name];
console.log('app = ', app);
checkAppStatus(name, app);
}
}
}
/**
* Checks the status of an app
*
* #param name - The name of the app
* #param app - The app that we're checking the status of
*/
function checkAppStatus(name, app) {
var req = rest.get(app.url);
req.on('complete', function(result, response) {
if(response.statusCode !== app.status) {
updateStatus(name, response.statusCode);
}
});
req.on('error', function(e) {
console.log('ERROR: ' + e.message);
});
req.on('timeout', function(data, response) {
console.log('Request timed out');
});
}
/**
* Updates the status of an app
*
* #param app - The app to update the status of
* #param status - The status to update the app to
*/
function updateStatus(name, status) {
apps[name].status = status;
apps[name].lastUpdatedAt = new Date();
}
function getStatuses() {
return apps;
}
function start() {
// Check every 5 seconds
setInterval(checkAllStatuses, 5*seconds);
}
module.exports.start = start;
module.exports.getStatuses = getStatuses;
Then i have a file which starts the process:
start.js
'use strict';
const status = require('./index');
status.start();
Then i have a file that I want to execute to get the current status of the apps:
consume.js
'use strict';
const status = require('./index');
console.log(status.getStatuses());
The problem is that consume.js just displays exactly what's in the initial app variable in index.js which is:
{
myApp: {
url: 'http://myUrl.com',
status: null,
lastUpdatedAt: new Date()
}
};
while the process running the start() command is displaying an updated status that is NOT null.
How can I make it so consume.js can see the value of a variable that start.js is updating?
I'd like to not have to use a datastore if possible. Worst case scenario is i write to a file, run redis, mongo, or some other datastore but i'm trying to avoid that making this app as simple as possible.
You are using the same code, index.js in both start.js and consume.js, but creating two separate instances of it when you run each file.
That is, the apps variable is changing in the instance created by start.js, but nothing in consume.js tells your code to change the apps variable.
If you are not saving a history of statuses, or saving the data to a datastore, what's the point in the start routine? You could just call checkAllStatuses and then return the results when you wish to consume the data.
Edit
Here's an example of combining the two files (start.js and consume.js) into one file. It also adds in a sample socket.io implementation since you stated that providing the statuses via websockets to clients was the evntual goal.
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
//// Your status library
var status = require('./index');
//// Start getting statuses
status.start();
app.listen(80);
//
// This is just the default handler
// in the socket.io example
//
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
// Someone wants the list of statuses
// This uses socket.io acknowledgements
// to return the data. You may prefer to use
// `socket.emit` instead or an altogether different socket library.
socket.on('status_fetch', function (data, callback_fn) {
callback_fn( status.getStatuses() );
});
});

Request Body is undefined in KOA

I have KOA Like below :
var koa = require('koa'),
bodyParser = require('koa-body-parser'),
router = require('koa-router'),
app = koa();
app.use(router(app));
app.use(bodyParser());
app.post('http://localhost/get',getit);
function *getit(){
console.log(this.req.body); //undefined
}
and then send a post reqeust via jquery ajax :
var xhr = $.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'http://localhost/getit',
data: {"name":"me"},
success: function(response) {
}
});
but in koa and in this.req i cant find my data. in google chrome developer tools i can see the header and everything send ok but i cant see it in koa.
Update
the correct is :
function *getit(){
console.log(this.request.body); //undefined
}
Interesting, I came across the same error, but my issue was the ordering of app.use() statements. The below does NOT work for me, and returns 'undefined' for this.request.body:
var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body-parser');
var app = koa();
app.use(router(app));
app.use(bodyParser());
app.post('/login', function *() {
this.response.body = this.request.body;
});
app.listen(3000);
However, if I reverse the order of the two app.use() statements to the following:
app.use(bodyParser());
app.use(router(app));
I can then see the elements in this.request.body. I'm using koa v0.5.5, koa-body-parser v1.0.0, koa-router v3.1.2, and node v0.11.12.
I would use the co-body module instead (the same module used internally by koa-body-parser). The code should looks like:
var koa = require('koa');
var _ = require('koa-route');
var parse = require('co-body');
var app = koa();
app.use(function* (next) {
this.req.body = yield parse(this);
yield next;
});
app.use(_.post('/login', function* () {
this.body = this.req.body;
}));
app.listen(3000);
The var body = yield parse(this); line does the trick, the parse method will try to parse any request but you can replace it with parse.json, parse.form or parse.text in case you need more control
koa uses middleware in the order you initialized them. so if you insert the router before the bodyparser it will not work. since your request wont pass to the parser before it gets to the router middleware, the request wont be parsed and koa will ignore the request.body. so the ordering is really important.
Solution
Acording to comment , the correct for me is this.request.body and this.req.body is not correct.

Creating a Mockup REST API

I'm currently trying to create a NodeJS server or something similar to mockup a REST API that reads in a JSON file and responds to requests with that data. I really only need GET requests supported. What is the best way to go about this?
Here's what I have so far:
/**
* Sample items REST API
*/
function ItemsRepository() {
this.items = [];
}
ItemsRepository.prototype.find = function (id) {
var item = this.items.filter(function(item) {
return item.itemId == id;
})[0];
if (null == item) {
throw new Error('item not found');
}
return item;
}
/**
* Retrieve all items
* items: array of items
*/
ItemsRepository.prototype.findAll = function () {
return this.items;
}
/**
* API
*/
var express = require('express');
var app = express();
var itemRepository = new ItemsRepository();
app.configure(function () {
// used to parse JSON object given in the body request
app.use(express.bodyParser());
});
/**
* HTTP GET /items
* items: the list of items in JSON format
*/
app.get('/items', function (request, response) {
response.json({items: itemRepository.findAll()});
});
/**
* HTTP GET /items/:id
* Param: :id is the unique identifier of the item you want to retrieve
* items: the item with the specified :id in a JSON format
* Error: 404 HTTP code if the item doesn't exists
*/
app.get('/items/:id', function (request, response) {
var itemId = request.params.id;
try {
response.json(itemRepository.find(itemId));
} catch (exception) {
response.send(404);
}
});
app.listen(8080); //to port on which the express server listen
I know that I would use the following to include the file, I just don't know how to stuff the data into Items.
var responseItemsData = require('./items-list.json');
This is trivial in node. You can load the data by requiring the .json file directly
var responseData = require('./my-json-file'); //.json extension optional
//Do this during your startup code, not during the request handler
Then to send it:
res.write(JSON.stringify(responseData));
The rest of the code you need is easily available in almost every node.js tutorial on the web.
You can use jasmine+sinon:
var Episode = Backbone.Model.extend({
url: function() {
return "/episode/" + this.id;
}
});
beforeEach(function() {
this.server = sinon.fakeServer.create();
});
afterEach(function() {
this.server.restore();
});
it("should fire the change event", function() {
var callback = sinon.spy();
this.server.respondWith("GET", "/episode/123",
[200, {"Content-Type": "application/json"},'{"id":123,"title":"Hollywood - Part 2"}']);
var episode = new Episode({id: 123});
// Bind to the change event on the model
episode.bind('change', callback);
// makes an ajax request to the server
episode.fetch();
// Fake server responds to the request
this.server.respond();
// Expect that the spy was called with the new model
expect(callback.called).toBeTruthy();
expect(callback.getCall(0).args[0].attributes)
.toEqual({id: 123,
title: "Hollywood - Part 2"});
});
more details in: https://github.com/cld-santos/simplologia/tree/master/javascript-lessons/src/test/javascript/Sinon
The easiest way is to simply use the static middleware.
var express = require('express');
var app = express();
app.use('/api', express.static(__dirname + '/data'));
app.use('.*', express.static(__dirname + '/assets'));
This assumes that you are eventually going to put the REST api at /api but that while you're testing your data is going to be in the data directory and that your CSS/JS/HTML is in the assets folder. In reality you can put it whereever you want, but you now can put all your dev json separate from your code.
I created a tool for this purpose
https://github.com/homerquan/kakuen

Accessing globals from node.js modules?

I want to separate some functions into a file named helpers.js, in which I have put the below shown code. What should I do to access the app variable from inside my method in order to be able to fetch my config element named Path?
Helpers = {
fs: require('fs'),
loadFileAsString: function(file) {
return this.fs.readFileSync( app.set('Path') + file)+ '';
}
}
module.exports = Helpers;
So from what I see you need the app variable form Express. You can send it as a function param to loadFileAsString, for ex:
helpers.js
Helpers = {
...
loadFileAsString: function(file, app) {
return this.fs.readFileSync( app.set('Path') + file)+ '';
}
}
module.exports = Helpers;
some_file.js
app = express.createServer();
...
helpers = require('./helpers.js');
helpers.loadfileAsString(file, app);
If you want the app to be global though you can do that also: global.app = app and you can access app everywhere without sending it as a function param.

Categories