Diving into node, I have a question on how an included script, can access the main's script methods or variables
For instance, say that I have a logger object initiated in the main script and I include another js file, which needs access to the logger. How can I do that, without injecting the logger to the included script.
//main node script
var logger = require('logger'),
app = require("./app.js")
//app.js
function something(){
//access logger here !!!!!!!
}
exports.something = something
Hope it is clear
Thanks
Try doing:
//main node script
var logger = require('logger'),
app = require("./app.js")(logger);
//app.js
var something = function (logger){
logger.log('Im here!');
}
module.exports = exports = something;
Edit:
If you want to split your main app's code into different files, on your main script file you can do something like: (This is how I'm splitting my main app.js into different sections)
// main app.js
express = require('express');
...
/* Routes ---------------------*/
require('./config/routes')(app);
/* Socket IO init -------------*/
require('./app/controllers/socket.io')(io);
/* Your other file ------------*/
require('./path/to/file')(app);
...
// config/routes.js
module.exports = function(app){
app.configure(function(){
app.get('/', ...);
...
}
}
// app/controllers/socket.io.js
module.exports = function(io){
// My custom socket IO implementation here
}
// ...etc
Edit 2:
Your function can also return a JS object, in case you want to do something on the main app.js with a custom script.
Example:
// main app.js
...
/* Some controller ---------------------*/
var myThing = require('./some/controller')(app);
myThing.myFunction2('lorem'); // will print 'lorem' on console
...
// some/controller.js
// Your function can also return a JS object, in case you want to do something on the main app.js with this require
var helperModule = require('helperModule');
module.exports = function(app){
var myFunction = function(){ console.log('lorem'); }
// An example to export a different function based on something
if (app.something == helperModule.something){
myFunction = function() { console.log('dolor'); }
}
return {
myFunction: myFunction,
myFunction2: function(something){
console.log(something);
}
}
}
You can also simply export a function or an object containing functions, without sending any parameter like this:
// main app.js
...
var myModule = require('./path/to/module');
myModule.myFunction('lorem'); // will print "lorem" in console
...
// path/to/module.js
module.exports = {
myFunction: function(message){ console.log(message); },
myFunction2: ...
}
Basically, whatever you put inside module.exports is what gets returned after the require() function.
module.exports is what is returned when you require the file. in #DavidOliveros example, that's a function that takes app or io as parameters. the function is executed right after the require takes place.
If you want to expose a method of the included script to the main, try this:
// child.js
module.exports = function(app){
var child = {};
child.crazyFunction = function(callback){
app.explode(function(){
callback();
});
};
child.otherFunction = function(){};
return child;
};
// app.js
var express = require('express');
var app = module.exports = express();
var child = require('./child.js')(app);
app.get('/', function(req, res){
child.crazyFunction(function(){
res.send(500);
});
});
Related
I am creating a node module and want the end user of this module to be able to pass it configuration options that will have an effect on the modules functions.
For example, with express you can create an express app and pass it to your routes as such:
const express = require('express');
const app = express();
require('./api/routes/login)(app)
and then in your routes file you can use that app -> /api/routes/login
//login.js
module.exports = function(app){
app.get('/login', function(req, res){//blah}
}
So what I am trying to do in my module is something similar in which an end user can pass an optional config parameters for the module's functions to use. This is was I was trying.....
In my module file:
const default_options = {"enabled":true}
module.exports = function(options) {
const options = options || default_options
exports.login = function(credentials) {
if(options.enabled == true){
//do something
}else{
//do something else
}
}
}
And then someone using the module would be able to do something like this:
//some js file
var options = {"enabled":false}
const mod = require('mymodule')(options)
mod.login(creds)
The error I am getting is 'Cannot read property 'login' of undefined'. I suspect it has something to do with me using exports twice but trying to figure out how to structure my module's js file to be able to use these options if passed it and apply them to the exposed functions.
Any help is appreciated, thank you!
You need to return an object from the exported function.
const default_options = {"enabled":true}
module.exports = function(options) {
const options = options || default_options
return {
login: function(credentials) {
...
}
}
}
I am working on node js. Day by day my app.js file is being longer. How can I reduce it. So that I can write code in other files. Still I have tried nothing but read about modules on google.
A simple example might go as follows, in your app.js file you set up your server:
const express = require('express');
const http = require('http');
const app = express();
const router = require('./router'); // <= get your router here
// Call the router, now you are listening
// using the routes you have set up in the other file
router(app);
const server = http.createServer(app);
server.listen(port, () => {
console.log('Server listening on port: ', port);
});
And in your router you export the app function using module.exports
module.exports = app => {
app.get('/', function(req, res) {
res.end('hello');
}
// all your routes here
}
Now you have separated out the logic of routing.
You can also export multiple methods or variables with the same process.
myFuncs.js
func1 function() {}
func2 function() {}
module.exports = {
func1
func2
}
(note here I am using ES6 it is the same as module.exports = { func1: func1, func2: func2 }
and then require them in the same way
const myFuncs = require('./myFuncs')
myFuncs.func1() // <= call func1
myFuncs.func2() // <= call func2
You can do the same operation with variables, and even combine with module.exports to shorten your code
mySecrets.js
module.exports = {secret_key: 'verysecretkey'}
app.js
const secret = require('./mySecrets')
That way you can keep your api_keys etc.. in a separate file, or even just variables that you want to import as required.
There are more details available here: https://developer.mozilla.org/en/docs/web/javascript/reference/statements/export
You can separate the code into different files and then use require to import them to app.js
var init = require('./config/init')(),
config = require('./config/config')
In the above code I have separated out some init function and config files to a separate files and I am importing it.
Write a module within an external file e.g.: ./hello.js:
module.exports = {
function1 : function(){console.log('hello module');}
};
Load that module within your app.js:
var hello = require('./hello.js');
// call your function
hello.function1();
In node.js projects I have seen require(path) as well as require(path)() what does extra paranthasis refers.
When should I use require(path) and require(path)()
The require() statement returns the module.exports property from within the module that is being loaded. What you do with that depends entirely on what the module set it to.
If the module set it to a function of some kind (often called a module constructor function), then it is natural to call it with var something = require('xxx')(...);
But, if the module just exports an object with properties on it, then it would actually be a programming error to try to call it.
So, it depends entirely upon what the module you are loading is exporting.
For example, when loading the file system module, it would just be:
var fs = require('fs');
The variable fs in this case is just an object (not a function) so you would not call it - you would just reference properties on it:
fs.rename(...)
Here's an example of a module exporting a constructor function that you would call with () after it:
// myRoutes.js
module.exports = function(app) {
app.get("/", function() {...});
app.get("/login", function() {...});
}
// app.js
// other code that sets up the app object
// ....
// load a set of routes and pass the app object to the constructor
require('./myRoutes')(app);
And, here's an example of a module just exporting properties so you would not call the module itself:
// myRoutes.js
module.exports.init = function(app) {
app.get("/", function() {...});
app.get("/login", function() {...});
}
// export commonly used helper function
module.exports.checkPath = function(path) {
// ....
}
// app.js
// other code that sets up the app object
// ....
// load a set of routes and then initialize the routes
var routeStuff = require('./myRoutes');
routeStuff.init(app);
if (routeStuff.checkPath(somePath)) {
// ...
}
I have an app.js file like so:
...
var socket = require('./app/sockets')(io)
var routes = require('./app/routes')(server, socket)
...
The sockets.js looks like so:
exports = module.exports = function(io) {
return {
emit: function() {
io.emit('hi', "Some stuff")
}
}
}
The routes.j file looks like so:
exports = module.exports = function(app, io) {
...
var user = require('./controllers/user')(io)
app.get({ path: '/users/:id', version: '1.0' }, user.getUserById);
...
}
Finally, my user.js file looks like so:
exports = module.exports = function(io) {
return {
...
getPersonById: function(req, res, next) {
....
io.emit("Hello")
...
},
....
}
}
Is there a better way to organize this? I feel like I am threading my io instance through 4 different files. I just want a singleton instance I can emit events on, from within my controller.
I,m using something like this, in express.io :
app.js
var router = require('./routes/router'),
express = require('express.io'),
app = new express();
app.http().io();
app.use(app.router);
app = router.index(app);
app.listen(3000);
./routes/router.js
exports.index = function(app){
var IndexIo = require(__maindir + '/routes/io/IndexIo');
app.io.route('page/action', IndexIo.action);
app.io.route('page/action2', IndexIo.action2);
return app;
};
/routes/io/IndexIo.js
exports.action = function(req){
doSomething();
req.io.emit('doSomething', {});
}
exports.action2 = function(req){
doSomething();
req.io.emit('doSomething', {});
}
I would like to pass additional data from app.js to express-resource routes and I have not figured out yet. How would you do that? Note that I'm using express-resource
// app.js
var myAddOnData = 'abc';
app.resource('users', './routes/user');
// user.js
exports.index = function (req, res) {
console.log(myAddOnData);
};
Thanks
These are the three approaches I can think of. Without the little I know about your specific problem, it sounds like middleware might be the way to do it.
With a global app variable
Create a value using app.set in app.js and then retrieve it using app.get in user.js.
Using a module
Store the information in an isolated module, then require() as needed. If this is running across multiple instances, you'd obviously want to store the values to disk as opposed to in memory.
// keystore.js
// -----------
module.exports.set = function(id, val) { /* ... */ };
module.exports.get = function(id) { /* ... */ };
// app.js
// -----------
var ks = require('./keystore');
ks.set = function("userInfo", "abc");
module.exports.get = function(id) { /* ... */ };
// user.js
// -----------
var ks = require('./keystore');
ks.get = function("userInfo", "abc");
(Maybe check out pot?)
Using Middleware
Use custom middleware to attach data to the request object which can then be accessed later in the route handlers.
//app.js
//------
var express = require('express')
, cookieSessions = require('./cookie-sessions');
var app = express();
app.use(express.cookieParser('manny is cool'));
app.use(cookieSessions('sid'));
// ...
//cookie-sessions.js
//------------------
module.exports = function(name) {
return function(req, res, next) {
req.session = req.signedCookies[name] || {};
res.on('header', function(){
res.signedCookie(name, req.session, { signed: true });
});
next();
}
}
via https://gist.github.com/visionmedia/1491756