I need to know the difference between these two approaches developer uses in nodeJS development to include a module.
First approach (passing module in app by importing it once and using it by passing as parameter or binding it to app as property )
Server.js (app entry point)
let app = require('express').express();
let Router = require("./routes");
let SomeModule = require("./some-module");
.....
.....
Router.mountAPI("/api", app, SomeModule);
.....
....
routes.js (Passing pre imported module to controllers in different files )
let Ctrl1fun = require("./ctrl1");
let Ctrl2fun = require("./ctrl2");
exports.mountAPI = function(mount, app, SomeModuleToUseInController) {
app.use(mount + '/endpoint1', Ctrl1fun(SomeModuleToUseInController));
app.use(mount + '/endpoint2', Ctrl2fun(SomeModuleToUseInController));
};
ctrl1.js (Controller for end point 1 )
module.exports = function(SomeModule) {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
ctrl2.js (Controller for end point 2 )
module.exports = function(SomeModule) {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
2.Second approach (Each controller importing the module)
Server.js (app entry point)
let app = require('express').express();
let Router = require("./routes");
.....
.....
Router.mountAPI("/api", app);
.....
....
routes.js (module imported in controllers )
let Ctrl1fun = require("./ctrl1");
let Ctrl2fun = require("./ctrl2");
exports.mountAPI = function(mount, app) {
app.use(mount + '/endpoint1', Ctrl1fun());
app.use(mount + '/endpoint2', Ctrl2fun());
};
ctrl1.js (Controller for end point 1 )
let SomeModule = require("./some-module");
module.exports = function() {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
ctrl2.js (Controller for end point 2 )
let SomeModule = require("./some-module");
module.exports = function() {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
Witch one is better if we consider
App size (API and controllers function in different controller files)
Application performance
Best practices
The difference in terms of size and performance will be negligible.
The second approach is simpler and I would consider it as the best one unless you need to inject different modules into the same controller type, e.g. a generic CRUD controller parameterized by model type
Related
I wanted to write a understandable code in node.js, so I want to put some functions, which are used very often, into other node.js files, and access them from there.
So I get a function, which calls a function from another node.js file and in this other node.js file, also another one is called.
Important to know, if I put all in one file, the code works, so it should be an issue with module export and using functions in another file.
I have one file, getting quotes from a decentralised exchange. Looking like this (quoter_uni_v2.js):
module.exports = function quotes_uni_v2(tokenIn, tokenOut, amountIn, router) {
const quotedAmountOut = router.getAmountsOut(amountIn.toString(), [
tokenIn,
tokenOut,
]);
return quotedAmountOut;
};
And I am importing this function in my second helper file (quotes_5.js) (It is splitted in two files, because in the second one I have to call the function multiple times):
var quotes_uni_v2 = require("./quotes_uni_v2");
module.exports = async function (router1, router2, route, amount_wei) {
console.log(route);
var amount_Out = await quotes_uni_v2.quotes_uni_v2(
route[1],
route[2],
amount_wei,
router1
);
...
return (
Math.round(ethers.utils.formatEther(amount_Out[1].toString()) * 100) / 100
);
};
After that I try to call the function in my main.js:
const quotes_uni_v2 = require("./quotes_uni_v2");
const quotes_5 = require("./quotes_5");
async function calc(route) {
amountOut = await new quotes_5(
quickswap_router,
sushiswap_router,
route,
amount_wei
);
return amountOut;
};
But calling the quotes function does not work... The error is:
TypeError: quotes_5 is not a constructor...
Can someone help me?
Thanks!
I'm trying to build an modular express.js server with a good structure.
Tryed to use the different routes as the components in react.
index.js
var syncsingle = require('./XYZ/syncsingle');
app.get('/sync', syncsingle);
syncsingle.js
if ( ** cool things **){
var one = require ('./XYZ/sync/one');
app.use('/sync', one);
}else{
var two = require ('./XYZ/sync/two');
app.use('/sync', two);
}
Maybe someone could help me out with that issue?
The code which is written in one.js and two.js should be just imported/included at the app.use(..) point. (e.g. in PHP the include('blaa.php') thing).
Thank you very much <3
Try passing the middleware or sub-app directly to your main app.
// index.js
var sync = require("./syncsingle.js")
app.use("/sync", sync)
// syncsingle.js
if ( ** cool things **){
module.exports = require ('./XYZ/sync/one');
} else {
module.exports = require ('./XYZ/sync/two');
}
It's also common to pass configuration to sub-apps or middleware.
var one = require ('./XYZ/sync/one');
var two = require ('./XYZ/sync/two');
module.exports = function sync(options) {
if ( ** cool things based on options ** ){
return one;
else {
return two;
}
}
In your main app file:
app.use("/sync", sync({ useOne: true })
i built an app on 1 page, and now i want to oragenize all of its functions and objects in seperate files and directories, and import them to the app.js file. but im having some problems with global objects, the the imported functions dosent recognize them.
example:
//app.js
const req_obj = require("./objectFile.js")
const tool = {
number:4
}
req_obj.obj.addFive() // this will print "cant read number of undefined"
//objectFile.js
const req_func = require("./function.js")
exports.obj = {
addFive:req_func.addFive
}
//function.js
exports.addFive = function(){
return tool.number + 5
}
i know that it might be that im doing all wrong, and this is not how you orgenize an app and call its function. i whould be really glad if some1 will explaine my how to orgenize an app, and call its functions the right way, if what i did is wrong.
The only possibility you have to get access to variables from multiple files is to have them in a separate file and export them like this:
// objects.js
const tool = {
number:4
}
exports.tool = tool
Which then makes your app.js look like:
//app.js
const req_obj = require("./objectFile.js")
const tool = require("./objects.js").tool
// this will read 9
console.log(req_obj.obj.addFive())
And your function.js then becomes:
const tool = require("./objects.js").tool
exports.addFive = function(){
return tool.number + 5
}
Hope it helps.
I can't solve this for almost four hours, and i can't find any helpful documentation for this kind of problems. This is the issue, I'm using pug/jade templates and i want to call function inside pug template to transform some data
This is the main template:
/** main template */
section
each pet in pets
.pet
.photo-column
img(src= pet.photo)
.info-column
h2= pet.name
span.species= (pet.species)
p Age: #{calculateAge(pet.birthYear)} //here I need to call calculateAge function
if pet.favFoods
h4.headline-bar Favorite Foods
ul.favorite-foods
each favFood in pet.favFoods
li!= favFood
/** end main template **/
This is the external function:
/** calculateAge.js **/
module.exports = function(birthYear) {
var age = new Date().getFullYear() - birthYear;
if (age > 0) {
return age + " years old";
} else {
return "Less than a year old";
}
};
/** end calculateAge.js **/
What shell I do to make this happen?
There may be better way to handle this, but I usually do it by importing the external module and then passing it as part of template context object. That means the code that renders the template should be something like:
const calculateAge = require("calculateAge"); // change path accordingly
router.get("/main", function(){
let pageInfo = {};
pageInfo.title = "Demo";
pageInfo.calculateAge = calculateAge;
res.render("main", pageInfo);
});
Now, you can access calculateAge in your template. If this module is used a lot in most of the templates, then you should pass it as part of res.locals or app.locals so that it is available for all templates without the need to append it for every path request.
In PUG options use locals property to import functions you want to use inside your templates.
const calculateAge = require('./calculate-age');
const config = {
pug: {
locals: {
calculateAge,
},
},
};
Then you can use it in all your templates like this (please note the extra unescaping tag !{}):
p Age: !{calculateAge(pet.birthYear)}
Like in raw HTML if you want JS to execute in a sepcific part you need a script tag to enclose the js you want to use.
span.species= (pet.species)
p Age:
.script
calculateAge(pet.birthYear)
if pet.favFoods
Make your function available in pug like this:
//assuming you're using express
app.set('view engine', 'pug');
app.locals.someFunction = input => input * 5;
// or
import {someOtherFunction} from "packageOrFile";
app.locals.someOtherFunction = someOtherFunction;
In your pug you then can do
span= someFunction(10)
span= someOtherFunction(123)
This is basically what mahish wrote in his comment, but it actually answers the question satisfactory and here's the documentation.
You can write javascript with .script tag
script.
$( document ).ready(function() {
calculateAge(params)
})
I have 2 routes defined in 2 separate files but a parameter RecordId is same for both the routes:
I am expecting that :
1) whenever I call /api/CountryMaster/:RecordId,
only RecordByIdCtry function should be called. &
2) when I am calling /api/commonMaster/:MasterName/:RecordId,
only RecordByIdCmn function should be called.
However, both functions are getting called with the order being as set in javascript.
i.e.
require('../app/routes/commonMaster.server.routes.js')(app);
require('../app/routes/countryMaster.server.routes.js')(app);
How can i stop these & ensure that only one method is called.
//CountryMaster.js
var ctrl = require('../../app/controllers/CountryMaster.server.ctrl.js');
var users = require('../../app/controllers/user.server.ctrl.js');
module.exports = function (app)
{
app.route('/api/CountryMaster')
.get(users.requiresLogin,ctrl.list)
.post(users.requiresLogin,ctrl.create);
app.route('/api/CountryMaster/:RecordId')
.get(ctrl.read)
.put(users.requiresLogin, ctrl.hasAuthorization, ctrl.update)
.delete(users.requiresLogin, ctrl.hasAuthorization, ctrl.delete);
app.param('RecordId', ctrl.RecordByIdCtry);
}
//CommonMaster.js
var ctrl = require('../../app/controllers/commonMaster.server.ctrl.js');
var users = require('../../app/controllers/user.server.ctrl.js');
module.exports = function (app)
{
app.route('/api/commonMaster/:MasterName')
.get(users.requiresLogin,ctrl.list)
.post(users.requiresLogin,ctrl.create);
app.route('/api/commonMaster/:MasterName/:RecordId')
.get(ctrl.read)
.put(users.requiresLogin, ctrl.hasAuthorization, ctrl.update)
.delete(users.requiresLogin, ctrl.hasAuthorization, ctrl.delete);
app.param('MasterName', ctrl.MasterName);
app.param('RecordId', ctrl.RecordByIdCmn);
}
How can I ensure that only one method is called..
In your code, app is always the same app, so you're basically declaring two handlers for the same parameter, which isn't going to work.
You should use entirely separate routers instead:
// CountryMaster.js
...
module.exports = function(app) {
var router = require('express').Router();
router.route('/')
.get(...)
.post(...);
router.route('/:RecordId')
.get(...)
.put(...)
.delete(...);
// The magic:
router.param('RecordId', ctrl.RecordByIdCtry);
// Mount the router on `/api/CountryMaster`
app.use('/api/CountryMaster', router);
};
And similar for CommonMaster.js.