Node.js: how to resolve a circular dependency - javascript

I know this question has been asked multiple times, but my case is specific:
I have three files, a controller.js, router.js and an app.js,
router.js imports controller.js, app.js imports router.js
I need to import something from app.js to controller.js, how would I do that?

you're probably better off restructuring your code to not need it. Maybe create a third class that uses the other two to accomplish what you need, if you have to use a function in app.js you can do like this:
before requiring you should exports express() and functions
app.js
const express = require("express");
const func = () => {
console.log("I'm in App");
};
var exportFiles = module.exports = {
app: express(),
func: func,
};
var { app } = exportFiles;
const fs = require("fs");
const path = require("path");
const bodyParser = require("body-parser");
app.listen(8080, () => {
console.log("server port is 8080")
})
contolers.js
const {func} = require('../app');
when you call func() in controller result is :
func() // I'm in App

Related

how to export modules that requires other modules

I'm working on a node js project that is getting bigger and bigger, and I'm trying to tidy up my code. This is just a case example.
this is my index.js:
const express = require('express')
const app = express()
const http = require('http').Server(app);
const io = require('socket.io')(http)
io.on('connection', socket => {
socket.on('message', () => doSomething())
})
http.listen(4000, () => console.log('server started'))
and I'd like to import doSomething from another file (say functions.js) like this:
function doSomething(){
console.log(io.sockets.adapter.rooms);
}
module.exports = { doSomething }
modifying index.js as follows:
[...]
const library = require('./functions.js')
[...]
socket.on('message', () => library.doSomething())
but of course:
io is not defined in functions.js.
QUESTION:
How could I import the required modules so that they are shared in both files?
Write your function.js file as below:
function doSomething(){
let self = this;
console.log(self.io.sockets.adapter.rooms);
}
module.exports = function (io) {
let self = this;
self.io = io;
return {
doSomething: doSomething.bind(self)
};
};
And its usage in index.js file will be:
const Library = require('./functions.js');
const library = Library(io);
socket.on('message', () => library.doSomething())
You will have to include the required packages in your functions.js.
Your functions.js should be something like
const io = require('socket.io')(http)
//Include other packages here
function doSomething(){
console.log(io.sockets.adapter.rooms);
}
//Other functions here
//Export all that you need to be exported
module.exports = { doSomething }

How do you use a JavaScript function from another file

So I have a file:
server.js
const express = require("express");
const app = express();
const rateLimit = require("express-rate-limit");
function rateLimiter(request, ms) {}
function startServer(port, dir) {}
And i want to call those two functions in another file
index.js
const express = require("server.js");
var rate = rateLimiter(100, 60000);
var server = startServer(8080, src);
How can I do that?
write something like:
module.exports = {rateLimiter, startServer}
You need to exports those functions and import them to other files.
Here is the export
server.js
const express = require("express");
const app = express();
const rateLimit = require("express-rate-limit");
function rateLimiter(request, ms) {}
function startServer(port, dir) {}
module.exports = {rateLimiter, startServer}
And here is the import
index.js
const express = require("server.js");
const {rateLimiter, startServer} = require('./server.js'); // your server.js file
var rate = rateLimiter(100, 60000);
var server = startServer(8080, src);

How to implement the router(express) inside class constructor in a separate js file

I am trying to do some optimization in a javascript project, I have two files ClassA.js and the appi.js. In the ClassA.js i have the functions that I use for different manipulations and in the api.js I call them via the requests I get. But now I want to move the http methonds inside a javascript class constructor. Like in the following code and I get some errors(and i dont think i got it in the right way, I am a beginner in Nodejs).
Some of the errors are like:
Router.use() requires middleware function but got a Object
And after i made some other changes i get
Json.path is not a function(on my server.js)
//I have imported(required) everything I need, express, router etc..
function classA(filename, jsonparser, url)
{
this.filename = filename;
this.jsonparser = jsonparser;
this.url = url;
router.get(url,function(req,res{classA.prototype.functionA(req,res)});
router.post(url, function(req,res){classA.prototype.functionB(req,res)});
}
classA.prototype.functionA = function(req,res)
{//Does something}
classA.prototype.functionA = function(req,res)
{//Does something}
module.exports = {
router:router,
classA:classA
}
//In the api.js
I want the following
let a = require('../ClasA.js');
let ObjA = new a.classA("filenamepath",JsonObject, "URL");
let express = require('express');
let app = express();
app.use(a.router);
module.exports = router
//Server
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const api = require('./server/routes/api');
const port = 3000;
const app = express();
//Some other code
app.use('/',api);
app.get('*',(req,res)=>{
res.sendfile(path.json(__dirname,'dist/index.html'));
});
//listen function

Express Route not firing when called

I have a route defined in my express app, and I have it inside a router that is imported into my app in the main file.
I have my router installed like this in index.js
const Routes = require('./routes');
app.use('/address', Routes.AddressRoutes);
in the routes folder, I have the address router exposed like this:
//./routes/index.js
const AddressRoutes = require('./address');
module.exports = Routes = {
AddressRoutes,
};
// ./routes/address.js
const router = require('express').Router();
const {Address} = require('./routeActions');
module.exports = () => {
router.post('/', Address.add);
return router;
};
// ./routes/routeActions/index.js
const Address = require('./user');
module.exports = {
Address,
};
// ./routes/routeActions/address.js
module.exports = Address = {
add: (req,res) => {....}
};
The issue is that I have a breakpoint in VS code inside the add() function, but the only thing that get's hit is the definition of the route, and not the actual handler. Am I making the modules too complicated? How can I get the handler to be called so I can debug it?
Two options to fix.
When adding the route definitions, run the function that is exported.
const Address = require('./address')();
Or when exporting the route definitions, simply export the router from the file.
module.exports = router; not module.exports = () => {routeHandlers.... return router}

Structure event listeners in Node.js [duplicate]

This question already has answers here:
How to separate routes on Node.js and Express 4?
(9 answers)
Closed 1 year ago.
In my NodeJS express application I have app.js that has a few common routes. Then in a wf.js file I would like to define a few more routes.
How can I get app.js to recognize other route handlers defined in wf.js file?
A simple require does not seem to work.
If you want to put the routes in a separate file, for example routes.js, you can create the routes.js file in this way:
module.exports = function(app){
app.get('/login', function(req, res){
res.render('login', {
title: 'Express Login'
});
});
//other routes..
}
And then you can require it from app.js passing the app object in this way:
require('./routes')(app);
Have a look at these examples: https://github.com/visionmedia/express/tree/master/examples/route-separation
In Express 4.x you can get an instance of the router object and import another file that contains more routes. You can even do this recursively so your routes import other routes allowing you to create easy-to-maintain URL paths.
For example, if I have a separate route file for my /tests endpoint already and want to add a new set of routes for /tests/automated I may want to break these /automated routes out into a another file to keep my /test file small and easy to manage. It also lets you logically group routes together by URL path which can be really convenient.
Contents of ./app.js:
var express = require('express'),
app = express();
var testRoutes = require('./routes/tests');
// Import my test routes into the path '/test'
app.use('/tests', testRoutes);
Contents of ./routes/tests.js:
var express = require('express'),
router = express.Router();
var automatedRoutes = require('./testRoutes/automated');
router
// Add a binding to handle '/tests'
.get('/', function(){
// render the /tests view
})
// Import my automated routes into the path '/tests/automated'
// This works because we're already within the '/tests' route
// so we're simply appending more routes to the '/tests' endpoint
.use('/automated', automatedRoutes);
module.exports = router;
Contents of ./routes/testRoutes/automated.js:
var express = require('express'),
router = express.Router();
router
// Add a binding for '/tests/automated/'
.get('/', function(){
// render the /tests/automated view
})
module.exports = router;
Building on #ShadowCloud 's example I was able to dynamically include all routes in a sub directory.
routes/index.js
var fs = require('fs');
module.exports = function(app){
fs.readdirSync(__dirname).forEach(function(file) {
if (file == "index.js") return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
Then placing route files in the routes directory like so:
routes/test1.js
module.exports = function(app){
app.get('/test1/', function(req, res){
//...
});
//other routes..
}
Repeating that for as many times as I needed and then finally in app.js placing
require('./routes')(app);
If you're using express-4.x with TypeScript and ES6, this would be the best template to use:
src/api/login.ts
import express, { Router, Request, Response } from "express";
const router: Router = express.Router();
// POST /user/signin
router.post('/signin', async (req: Request, res: Response) => {
try {
res.send('OK');
} catch (e) {
res.status(500).send(e.toString());
}
});
export default router;
src/app.ts
import express, { Request, Response } from "express";
import compression from "compression"; // compresses requests
import expressValidator from "express-validator";
import bodyParser from "body-parser";
import login from './api/login';
const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.get('/public/hc', (req: Request, res: Response) => {
res.send('OK');
});
app.use('/user', login);
app.listen(8080, () => {
console.log("Press CTRL-C to stop\n");
});
Much cleaner than using var and module.exports.
Full recursive routing of all .js files inside /routes folder, put this in app.js.
// Initialize ALL routes including subfolders
var fs = require('fs');
var path = require('path');
function recursiveRoutes(folderName) {
fs.readdirSync(folderName).forEach(function(file) {
var fullName = path.join(folderName, file);
var stat = fs.lstatSync(fullName);
if (stat.isDirectory()) {
recursiveRoutes(fullName);
} else if (file.toLowerCase().indexOf('.js')) {
require('./' + fullName)(app);
console.log("require('" + fullName + "')");
}
});
}
recursiveRoutes('routes'); // Initialize it
in /routes you put whatevername.js and initialize your routes like this:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index', { title: 'index' });
});
app.get('/contactus', function(req, res) {
res.render('contactus', { title: 'contactus' });
});
}
And build yet more on the previous answer, this version of routes/index.js will ignore any files not ending in .js (and itself)
var fs = require('fs');
module.exports = function(app) {
fs.readdirSync(__dirname).forEach(function(file) {
if (file === "index.js" || file.substr(file.lastIndexOf('.') + 1) !== 'js')
return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
I am trying to update this answer with "express": "^4.16.3". This answer is similar to the one from ShortRound1911.
server.js:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const db = require('./src/config/db');
const routes = require('./src/routes');
const port = 3001;
const app = new express();
//...use body-parser
app.use(bodyParser.urlencoded({ extended: true }));
//...fire connection
mongoose.connect(db.url, (err, database) => {
if (err) return console.log(err);
//...fire the routes
app.use('/', routes);
app.listen(port, () => {
console.log('we are live on ' + port);
});
});
/src/routes/index.js:
const express = require('express');
const app = express();
const siswaRoute = require('./siswa_route');
app.get('/', (req, res) => {
res.json({item: 'Welcome ini separated page...'});
})
.use('/siswa', siswaRoute);
module.exports = app;
/src/routes/siswa_route.js:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({item: 'Siswa page...'});
});
module.exports = app;
If you want a separate .js file to better organize your routes, just create a variable in the app.js file pointing to its location in the filesystem:
var wf = require(./routes/wf);
then,
app.get('/wf', wf.foo );
where .foo is some function declared in your wf.js file. e.g
// wf.js file
exports.foo = function(req,res){
console.log(` request object is ${req}, response object is ${res} `);
}
One tweak to all of these answers:
var routes = fs.readdirSync('routes')
.filter(function(v){
return (/.js$/).test(v);
});
Just use a regex to filter via testing each file in the array. It is not recursive, but it will filter out folders that don't end in .js
I know this is an old question, but I was trying to figure out something like for myself and this is the place I ended up on, so I wanted to put my solution to a similar problem in case someone else has the same issues I'm having. There's a nice node module out there called consign that does a lot of the file system stuff that is seen here for you (ie - no readdirSync stuff). For example:
I have a restful API application I'm trying to build and I want to put all of the requests that go to '/api/*' to be authenticated and I want to store all of my routes that go in api into their own directory (let's just call it 'api'). In the main part of the app:
app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));
Inside of the routes directory, I have a directory called "api" and a file called api.js. In api.js, I simply have:
var express = require('express');
var router = express.Router();
var consign = require('consign');
// get all routes inside the api directory and attach them to the api router
// all of these routes should be behind authorization
consign({cwd: 'routes'})
.include('api')
.into(router);
module.exports = router;
Everything worked as expected. Hope this helps someone.
index.js
const express = require("express");
const app = express();
const http = require('http');
const server = http.createServer(app).listen(3000);
const router = (global.router = (express.Router()));
app.use('/books', require('./routes/books'))
app.use('/users', require('./routes/users'))
app.use(router);
routes/users.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'John Smith'})
}
module.exports = router
routes/books.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'Dreams from My Father by Barack Obama'})
}
module.exports = router
if you have your server running local (http://localhost:3000) then
// Users
curl --request GET 'localhost:3000/users' => {name: 'John Smith'}
// Books
curl --request GET 'localhost:3000/books' => {name: 'Dreams from My Father by Barack Obama'}
I wrote a small plugin for doing this! got sick of writing the same code over and over.
https://www.npmjs.com/package/js-file-req
Hope it helps.
you can put all route functions in other files(modules) , and link it to the main server file.
in the main express file, add a function that will link the module to the server:
function link_routes(app, route_collection){
route_collection['get'].forEach(route => app.get(route.path, route.func));
route_collection['post'].forEach(route => app.post(route.path, route.func));
route_collection['delete'].forEach(route => app.delete(route.path, route.func));
route_collection['put'].forEach(route => app.put(route.path, route.func));
}
and call that function for each route model:
link_routes(app, require('./login.js'))
in the module files(for example - login.js file), define the functions as usual:
const login_screen = (req, res) => {
res.sendFile(`${__dirname}/pages/login.html`);
};
const forgot_password = (req, res) => {
console.log('we will reset the password here')
}
and export it with the request method as a key and the value is an array of objects, each with path and function keys.
module.exports = {
get: [{path:'/',func:login_screen}, {...} ],
post: [{path:'/login:forgotPassword', func:forgot_password}]
};

Categories

Resources