routes with multiple files nodejs - javascript

i want to route in multiple files
var routes=require('./routes');
in the routes/index.js
exports.inicio=require('./inicio')
exports.home=require('./home')
in the inicio.js
exports.index=function(req,res){res.render('index/index',{title: 'Bienvenido a Inmoweb'});}
in the home.js
exports.nosotros=function(req, res){res.render('index/nosotros',{title:'Nosotros'});}
when i console.log(routes)
{
inicio: {index:[function]},
home: {nosotros:[function]}
}
so i call in app
app.get('/',routes.inicio.index);
but i want to call like this
app.get('/',routes.index);
app.get('/nosotros',routes.nosotros);
and the console.log supose to be????
{
index:[function],
nosotros:[function]
}
how to do that??? tnx all

Your routes/index.js can do the following:
exports.index = require('./inicio').index
exports.nosotros = require('./home').nosotros
You can make this even shorter by assigning directly to module.exports in inico.js:
module.exports = function(req,res){res.render('index/index',{title: 'Bienvenido a Inmoweb'});}
Now you can do this in routes/index.js:
exports.index = require('./inicio') //See the difference?
// require('./inicio') now directly exports your route
exports.nosotros = require('./home').nosotros
Get the idea? :)

Related

how to use global variable(sharable variables) in Node.js&Express

I have a file called data.js for keeping data as memory database.
var express = require('express');
var app = express();
var aList;
var bList;
var cList;
module.exports = app;
And I want to initialise data when I start the server. So, I implemented init() in app.js
...
var data = require('./data'); // data.js is located in the same folder.
app.set(...);
app.use(...);
...
init();
...
});
fun init(){
console.log("Hello!");
aList = getDumpDataList(10); // I also tried with 'data.aList = getDumpDataList(10);' but didn't work.
console.log(JSON.stringify(aList));
}
fun getDumpDataList(n){
var list;
... // for loop to generate random elements.
return list;
}
module.exports = app;
When I printed with console.log(), Hello! is printed but aList isn't printed but undefined
And I also want to use the data in routers under routes folder.
So, what I did is.
...
var data = require('./data');
route.get("/...", function(req, res, next){
console.log(JSON.stringify(aList));
...
});
But it is also undefined.
I am just making simple test server that initialise data whenever I re-run.
How can I share variables between the js files?
You do not export those vars:
const express = require('express');
const app = express();
let aList;
let bList;
let cList;
module.exports.app = app;
module.exports.aList = aList;
module.exports.bList = bList;
module.exports.cList = cList;
...but i would not put express in data.js, rather put it in app.js.
I would also initialize those vars with initial values in data.js, if the initial data does not depend on something else.
Last but not least: Do not use var anymore, use let and const instead. It is supported since Node 6+ (https://node.green/). I replaced it in the code.

expressJS require a file which has route object from two different place does not work

I am working on an expressJS project. I have a route file named send_email.js, and I want to use parts of this file from two different places. These places are index.js and user.js.
So I added the following line for both of index.js and users.js:
const send_email = require("./send_mail");
But user.js is giving me an error because send_email is undefined. And then I just delete the same line from index.js and everything goes fine. I can reach send_mail in user.js, and it is what I expect.
Am I overlooking something about requiring files in expressJS? I can use this technique effectively in other projects. Are there expressJS specific things which cause this error?
I created same situation in another tiny project and its' codes like these:
// ------------------------index.js -----------------------
const express = require("express");
const app = express();
/* if coment this two line every thing goes fine */
const mylog = require("./deneme1").mylog;
mylog();
/* if coment this two line every thing goes fine */
const yourlog = require("./deneme2").yourlog;
const route = require("./deneme1").route;
console.log('route :', route);
yourlog();
app.get("/", (req, res)=>{
res.send("OK!");
})
app.listen(3000, () => { "listening on "+3000});
// --------------deneme1.js -------------------------
const express = require("express");
const route = express.Router();
const yourlog = require("./deneme2").yourlog;
console.log('yourlog mmm:', yourlog);
route.get("/deneme", function(req, res){
mylog();
res.send("OK!");
});
function mylog () {
console.log("mylog in deneme1.js");
};
module.exports.route = route;
module.exports.mylog = mylog;
// ------------------deneme2.js-----------------
const express = require("express");
const route = express.Router();
const mylog = require("./deneme1").mylog;
console.log('mylogxx :', mylog);
function yourlog(){
console.log("yourlog deneme2");
mylog();
console.log("----");
}
module.exports.yourlog = yourlog;
deneme1.js and deneme2.js require each other and express.js require both of deneme1.js and deneme2.js.
Did you export in your send_mail.js file? You should export whatever function you want to reuse . And use import wherever you need it. Instead of require.
For reference :MDN
I have realized that my problem is related "cyclic dependencies" between my route files. It is kind of design mistake. And there is a stackoverflow question/solution about it:
how-to-deal-with-cyclic-dependencies-in-node-js

Node JS res.sendFile() not working

I'm getting ReferenceError: main is not defined
when I open up the http://localhost:3000/
Here I try to open up the main.html located in views directory
This is my app.js
const express = require('express'),
app = express(),
config = require('./config/index'),
routes = require('./routes/route');
app.use(express.static(`${__dirname}/public`));
app.use(express.static(`${__dirname}/views`));
app.use('/',routes);
app.listen(config.port,()=>{
console.log(`Listing at port ${config.port}`)})
This is my route.js
const express = require('express'),
router = express.Router(),
helpers = require('../helpers/index');
router.route('/')
.get(helpers.index)
module.exports = router
This is my helpers/index.js
var user = require('../user/user');
exports.index = (req,res)=>{
if(user.name == ''){
res.sendFile(main.html);
}
else{
res.sendFile(chat.html)
}
}
module.exports = exports;
Directory Structure
>helpers
>index.js
>routes
>route.js
>user
>user.js
>views
>main.html
>chat.html
app.js
pacakage.json
Change:
res.sendFile(main.html);
to:
res.sendFile("main.html");
Without the quotes, it's trying to interpret main as a Javascript object which it looks for the .html property on. But, there is apparently no object named main so you get ReferenceError: main is not defined. You want to pass a string here instead.
Same for res.sendFile("chat.html");
If the files are not local to this module's directory, then you need to build a more complete path that specifies their location. Given the file hierarchy you show, I think that might be something like this:
const path = require('path');
const options = {root: path.join(__dirname, "../views")};
res.sendFile("main.html", options);
var user = require('../user/user');
var path = require('path');
exports.index = (req,res)=>{
if(user.name == ''){
res.sendFile(path.resolve('views/main.html'));
}
else{
res.sendFile(path.resolve('views/chat.html'))
}
}
module.exports = exports;
In addition to jfriend00's answer, you must also, build the correct absolute path, using the global __dirname variable in node.
So your path will be something like: res.sendFile(__dirname + "/main.html")
or, depending on your folder structure: res.sendFile(__dirname + "/someadditionalfoldrs/main.html")
or, construct the path using "./" if applicable, like "./main.html";

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

How to access variables declared in main app.js in separate route files in node.js Express 2.5.5?

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

Categories