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.
Related
I have the following piece of code in my "getpics.js" file:
var path = require('path');
var fs = require('fs');
const directoryPath = './public/img/slider'
exports.fileOnDisk = function(){
fs.readdir(directoryPath, function (err, files) {
//handling error
if (err) {
return console.log('Unable to scan directory: ' + err);
};
console.log(files);
return files;
});
}
return module.exports;
here is my mail.js callup of the module:
var getpics = require('./public/js/slider/getpics.js');
getpics.fileOnDisk();
and this is the printout on the console:
[ 'next.png', 'next_hover.png', 'prev.png', 'prev_hover.png',
'slide1.jpg', 'slide2.jpg', 'slide3.jpg', 'slide4.jpg',
'slide5.jpg' ]
all good until now.
The question is why I cannot export the "files" outside this module, for example in a variable, to use them in my application?
The reason why you're unable to export those files directly is due to the async nature of NodeJS, specifically to the file system call fs.readdir. As that function call is processed in an asynchronous fashion, the code execution will proceed, and you won't be able to access whatever the result of that function is in order to export it. You can read more about it in the about section of NodeJS.
However, the NodeJS file system API does provide synchronous methods. Specifically to your case fs.readdirSync. Using that in your code you would end up with something like:
var path = require('path');
var fs = require('fs');
const directoryPath = './public/img/slider'
exports.fileOnDisk = fs.readdirSync(directoryPath, {encoding: 'utf8'})
You could then import this module and access the array of directories straight from fileOnDisk.
Be careful however as this code will be blocking.
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
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
I'm working on an node.js application with several dozen modules and using bunyan for logging (JSON output, multiple configurable streams). I've been looking for good examples of how to implement a instance across all the modules, but haven't seen what appears to be a really clean example I can learn from.
Below illustrates an approach that works, but seems quite inelegant (ugly) to me. I'm new to node & commonjs javascript in general, so looking for recommendations on how to improve it.
module: ./lib/logger
// load config file (would like this to be passed in to the constructor)
nconf.file({ file: fileConfig});
var logSetting = nconf.get('log');
// instantiate the logger
var Bunyan = require('bunyan');
var log = new Bunyan({
name: logSetting.name,
streams : [
{ stream : process.stdout,
level : logSetting.stdoutLevel},
{ path : logSetting.logfile,
level : logSetting.logfileLevel}
],
serializers : Bunyan.stdSerializers
});
function Logger() {
};
Logger.prototype.info = function info(e) { log.info(e) };
Logger.prototype.debug = function debug(e) { log.debug(e) };
Logger.prototype.trace = function trace(e) { log.trace(e) };
Logger.prototype.error = function error(e) { log.error(e) };
Logger.prototype.warn = function warn(e) { log.warn(e) };
module.exports = Logger;
module: main app
// create the logger
var logger = require('./lib/logger)
var log = new logger();
// note: would like to pass in options --> new logger(options)
module: any project module using logger
// open the logger (new, rely on singleton...)
var logger = require('./lib/logger');
var log = new logger();
or view the gist
any recommendations?
EDIT:
I've modified the constructor, making the singleton pattern explicit (rather than implicit as part of the 'require' behaviour.
var log = null;
function Logger(option) {
// make the singleton pattern explicit
if (!Logger.log) {
Logger.log = this;
}
return Logger.log;
};
and then changed the initialization to take an options parameter
// initialize the logger
Logger.prototype.init = function init(options) {
log = new Bunyan({
name: options.name,
streams : [
{ stream : process.stdout,
level : options.stdoutLevel},
{ path : options.logfile,
level : options.logfileLevel}
],
serializers : Bunyan.stdSerializers
});
};
Singleton pattern in nodejs - is it needed?
Actually, singleton is perhaps not needed in Node's environment. All you need to do is to create a logger in a separate file say, logger.js:
var bunyan = require("bunyan"); // Bunyan dependency
var logger = bunyan.createLogger({name: "myLogger"});
module.exports = logger;
Then, retrieve this logger from another module:
var logger = require("./logger");
logger.info("Anything you like");
if you are using express with node.js then you can try this.
By default, logging is disabled in Express. You have to do certain stuff to get logs working for your app. For access logs, we need to use the Logger middleware; for error logs we will use Forever.Hope it will help you..
Here is a good example How to Logging Access and Errors in node.js
I just started using a new version of Express (2.5.5) that by default creates a ./routes directory along with ./views and ./public
Inside of routes there is a index.js file which contains:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Express' })
};
by default (after running express from the commandline) and this is the routes section in the main app.js:
// Routes
app.get('/', routes.index);
I've set up a variable for a redis client in the main app.js:
var redis = require('redis'),
db = redis.createClient();
and I was wondering how I could access the methods of db (and whatever other modules I require in app.js) in the files contained in ./routes
I really liked Jamund's solution, but I would extend the concept to this:
// db.js
var redis = require('redis');
module.exports = redis.createClient();
// index.js
var db = require(.'/db')
// whatever other file
var db = require(.'/db')
// do something with db
db.disconnect();
both db on index and other file would get the same instance of the redis client
Just call this at the top of your files. Requires are in a shared space, so you can re-require the file multiple times and it will always reference the same version. If you want to be fancy you can create your own db module that does something like this, to prevent double creating clients:
// db.js
var db
var redis = require('redis')
exports.connect = function() {
if (!db) db = redis.createClient()
return db
}
exports.disconnect = function() {
redis.quit()
db = null
}
// index.js
var dbHelper = require(.'/db')
var db = dbHelper.connect()
// whatever other file
var dbHelper = require(.'/db')
var db = dbHelper.connect() // won't connect twice
You can either create an app global and hang the vars you want to share off that or you can use an initializer function in your routes file
f.e.
// app.js
var app = express.createServer()
, db = require('redis').createClient();
require('./routes').with(app, db);
// routes.js
module.exports.with = function(app, db) {
app.get('/',function(r,s) { s.end('Sweet');});
}