Trying to use exports.create from another module in Node.js - javascript

I want to use code from one module in another module.
Module1Directory has the following files:
Module1.js
exports.create = function(req, res) {
function something(){}
}
Index.js:
'use strict';
var express = require('express');
var controller = require('./Module1.js');
var router = express.Router();
router.post('/', controller.create);
module.exports = router;
Module2Directory has the following files:
Module2.js
var confusing = require('../Module1Directory/Module1.js');
exports.create = function(req, res){
confusing.create.something();
}
Index.js:
'use strict';
var express = require('express');
var controller = require('./Module2.js');
var router = express.Router();
router.post('/', controller.create);
module.exports = router;
the function something run in Module2 returns 'undefined is not a function' in the terminal. What's wrong?

Your create is a function, but you're treating it as a non-function object. You'd have to call it, and it would have to return an object with a something property:
Module1.js:
exports.create = function(req, res) {
function something(){}
return {something: something}; // <===
};
Module2.js
var confusing = require('../Module1Directory/Module1.js');
exports.create = function(req, res){
confusing.create(req, res).something();
// ^^^^^^^^^^
};

Related

How to pass DB object in multi router setting in ExpressJS?

I would like to make multiple router settings like the example in ExpressJS Doc.
I have index.js , api1 , api2 like below.
How can I pass the db object from index.js to api1 and api2?
I try with
app.use('/api/v1', require('./controllers/api_v1')(db));
but it shows errors:Router.use() requires a middleware function but got a Object
index.js:
var express = require('../..');
const knex = require('knex');
const config = require('./config');
var app = module.exports = express();
const db = knex(config.db);
app.use('/api/v1', require('./controllers/api_v1'));
app.use('/api/v2', require('./controllers/api_v2'));
app.get('/', function(req, res) {
res.send('Hello from root route.')
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
api_v1.js
var express = require('../../..');
var apiv1 = express.Router();
apiv1.get('/', function(req, res) {
res.send('Hello from APIv1 root route.');
});
apiv1.get('/users', function(req, res) {
res.send('List of APIv1 users.');
});
module.exports = apiv1;
api_v2.js
var express = require('../../..');
var apiv2 = express.Router();
apiv2.get('/', function(req, res) {
res.send('Hello from APIv2 root route.');
});
apiv2.get('/users', function(req, res) {
res.send('List of APIv2 users.');
});
module.exports = apiv2;
You could export the db object from a database.js file and require it in the index.js file as well as every other file where you need database access. Or, an easier but uglier method, would be to make the variable global via global.db = db. You could then use db everywhere in your Node.JS application.

nodejs problems passing a paramenter to module

I am having a headache trying to pass a variable to module.
In node.js I have the following distribution:
The node.js server (server.js):
// modules =================================================
var express = require('express');
var app = express();
// configuration ===========================================
app.set('port', process.env.PORT || 3000);
var myRoutes = require('./my.router')(app);
// Start the Server ===========================================
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
exports = module.exports = app; // expose app
The router (my.router.js):
var myCtrl = require('./my.controller');
module.exports = function(app) {
app.get('/api/some', myCtrl.some);
app.get('/api/other', myCtrl.other);
}
The controller(my.controller.js):
exports.some = function(req, res, next) {
res.send('some');
};
exports.other = function(req, res, next) {
res.send('other');
}
This works ok. My problems come when I try to use socket.io and emit an event when /api/some is called.
I need the app object to create the server so I change the router to:
var myCtrl = require('./my.controller');
module.exports = function(app) {
var server = require('http').createServer(app);
var io = require('socket.io')(server);
server.listen(3001);
app.get('/api/some', myCtrl.something);
app.get('/api/other', myCtrl.other);
}
And I change the controller to emit the event when /api/some is called:
exports.some = function(req, res, next) {
io.sockets.emit('my_event', {});
res.send('some');
};
exports.other = function(req, res, next) {
res.send('other');
}
Inside the controller I need the io object to make this work.
It may sound simple to someone with a bit more knowledge of node.js but I am not capable of making it work.
I would need something like app.get('/api/some', myCtrl.something(io)) but this is not working...
Can't you just split your code:
var server = require('http').createServer(app);
var io = require('socket.io')(server);
At this stage you have your io, then
var myCtrl = require('./my.controller')(io);
You pass the io as a parameter to your controller which should then be a function like:
/* my.controller.js */
module.exports = function(io) {
some: function(req, res, next) {
io.sockets.emit('my_event', {});
res.send('some');
},
other: function(req, res, next) {
res.send('other');
}
}
Or something along those lines.
// modules =================================================
var express = require('express');
var app = express();
// configuration ===========================================
app.set('port', process.env.PORT || 3000);
var server = require('http').createServer(app);
app.io = require('socket.io')(server); //add io key to app
server.listen(3001);
require('./my.router')(app);
app.Controllers = {};
app.Controllers.myCtrl = require('./my.controller')(app); //pass app to controllers as well (not necessary but you can bootstrap your controllers at the start instead of requiring them in files)
//app.Controllers.anotherCtrl = require('./my.anotherController')(app); //example
// Start the Server ===========================================
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
exports = module.exports = app; // expose app
Controller
module.exports = function(app) {
var Controller = {};
var io = app.io;
Controller.some = function(req, res, next) {
io.sockets.emit('my_event', {});
res.send('some');
};
Controller.other = function(req, res, next) {
res.send('other');
}
return Controller;
};
Route
module.exports = function(app) {
var myCtrl = app.Controllers.myCtrl;
app.get('/api/some', myCtrl.some);
app.get('/api/other', myCtrl.other);
}
You can use the request object to pass the data between different routes.
module.exports = function(app) {
var server = require('http').createServer(app);
var io = require('socket.io')(server);
server.listen(3001);
//middleware used to assign 'io' to the request object
function passIoObject(req, res, next) {
req.myIo = io;
next()
}
// either use app.use(passIoObject) if io should be available for all following routes
// or pass it only to specific routes
app.get('/api/some', passIoObject, myCtrl.something);
app.get('/api/other', myCtrl.other);
}
and in your main controller you would access it using:
exports.some = function(req, res, next) {
req.myIo.sockets.emit('my_event', {});
res.send('some');
}
Beside that you should avoid a construct like:
module.exports = function(app) {
var server = require('http').createServer(app);
var io = require('socket.io')(server);
server.listen(3001);
app.get('/api/some', myCtrl.something);
app.get('/api/other', myCtrl.other);
}
The larger the code becomes the more problems you will have with maintainability, because you will always need look into the require('./my.router') file to see which paths/prefix are handled by the code.
Instead write it that way:
module.exports = function(app) {
var server = require('http').createServer(app);
var io = require('socket.io')(server);
server.listen(3001);
var router = express.Router();
router.get('/some', myCtrl.something);
router.get('/other', myCtrl.other);
return router;
}
And in server.js
var myRoutes = require('./my.router')(app);
app.use('/api', myRoutes);

load async configs before export

I need to load some async config before run my app, something like this:
var express = require('express');
var router = express.Router();
var myModule = require("myModule");
myModule.create().generateModel().then(tagger => {
router.post('/tag', function(req, res, next) {
res.json(tagger.tag(req.body.text));
});
module.exports = router;
});
but this does not work because require is sync. How can I make this work? How can I reutilize "tagger" in other modules?
You don't need to set module.exports asynchronously because you're exporting the router which is already defined synchronously:
var express = require('express');
var router = express.Router();
var myModule = require("myModule");
myModule.create().generateModel().then(tagger => {
router.post('/tag', function(req, res, next) {
res.json(tagger.tag(req.body.text));
});
});
module.exports = router;

Why is my route not being hit?

Hi I have an express router that seems to not get hit when I navigate to the proper route. In my app.js:
var auth = require('./routes/auth');
app.use('/auth', auth);
In my routes/auth.js
var express = require('express');
var authRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
var router = function(){
authRouter.route('/signUp')
.post(function (req, res){
console.log("Hello world");
});
return authRouter;
};
module.exports = router;
In my index.jade:
form.login-form(role='form', action='/auth/signUp', method='post', name='signUpForm' )
.form-group
label.sr-only(for='form-username') Username
input#form-username.form-username.form-control(type='text', name='userName', placeholder='Email...')
.form-group
label.sr-only(for='form-password') Password
input#form-password.form-password.form-control(type='password', name='password', placeholder='Password...')
button.btn(type='submit') Sign up!
However when I try to go to /auth/signUp all I get in terminal is: GET /auth/signUp - - ms - -
POST /auth/signUp - - ms - -
It seems to me that my auth/signUp is never hit. I was originally trying to console.log my req.body however I cannot even log a hello world.
You're wrapping your router in a function which is never called. Try just doing this instead:
var express = require('express');
var authRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
authRouter.route('/signUp').post(function (req, res){
console.log("Hello world");
});
module.exports = authRouter;
first, you shouldn't really use cased urls like signUp. Try this:
var express = require('express');
var authRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
var router = function(){
authRouter.post('/sign-up', function (req, res) {
console.log("Hello world");
});
return authRouter;
};
module.exports = router;
You are using wrong way of defining routers. Use this way instead.
var express = require('express');
var authRouter = express.Router();
authRouter.post('signUp', function(req, res) {
// in this code block you have to render text, html or object
res.render('index'); // or may be res.json(some_obj);
})

Using variables in modules of Node Express application

The express generator creates an app like this:
in the main app.js:
var app = express();
//...
var routes = require('./routes/index');
app.use('/', routes);
//...
in routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
What is the best way to use variables that I define in app.js in the index.js?
For example, before defining the routes, I set up the mongoose model:
var myModel;
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.once('open', function (callback) {
//load schemas
var dbSchema = require('./schema');
myModel = mongoose.model('mymodel', dbSchema.myModel);
});
How can I use 'myModel' in the routes module?
You should define your models outside app.js, in their own separate files for each separate model, and export that model which you can then require in various places you need it. Your model definition doesn't actually need to be inside db.once('open'
For example: if you have a model User you should define it in its own file like this:
db/user.js
var mongoose = require('mongoose');
var schema = mongoose.Schema({
…
});
var model = mongoose.model('user', schema);
module.exports = model;
This way if you want to use the User model inside your routes/index.js:
…
var User = require('../db/user');
router.get('/user/:id', function(req, res, next) {
User.findById(req.params.id, function(err, user){
res.render('user', { title: 'Express', user: user});
});
});
Pass it as a parameter when you require your router in your app.js file. You're going to have to slightly modify your index.js file
var express = require('express');
var myRouter = function(myModel) {
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
// You can use your myModel model here
return router;
}
module.exports = myRouter
Now inside your app.js
var app = express();
//...
// Pass myModel as a parameter
var routes = require('./routes/index')(myModel);
app.use('/', routes);
//...

Categories