For a Node.js project I have been working on since I was a teenager with a large amount of different files, I have a bunch of objects that are declared and initialised in index.js. All of my function calls start here as well.
To make sure other files can access these objects if needed, I have been passing them along as parameters for every main function, which now that I reconsider it, seems very inefficient: These objects are never modified and will be the same each time the functions are called anyway.
Instead of passing these often used objects as parameters each time, could I make it so I can access them on-demand from any of the files in the project? If it makes it clearer, they are mostly references to a database which is why they don't change.
What I already considered:
index.js: exports.getClient = function() { return client; }; This didn't work for me, because if I use require('./index.js') in any file from where I want to access client that'll initialise index.js again, resulting in double listeners and stuff.index.js on startup. Then there is no problem when I require that file, because that wouldn't call the initialisation a second time. If it's possible though, I'd rather keep these objects' initialisation in index.js.Now that I think about it, I don't know if two files calling require on each other would even cause them to continuously execute each other in the first place - I was only executing a specific file that was requiring (and thus executing) index.js during testing instead of everything. I'll test this after sleeping and post an edit, but still post this for now.
Example of my code:
// index.js
const client = new Client();
const db = initialiseDb();
const dbDoc1 = db.doc('1');
const dbDoc2 = db.doc('2');
const dbDoc3 = db.doc('3');
client.on('event', (data) => {
require('./someFile').someMethod(data, client, dbDoc1, dbDoc2, dbDoc3);
}
So instead of writing require('./someFile').someMethod(data, client, dbDoc1, dbDoc2, dbDoc3);, I'd much rather use require('./someFile').someMethod(data); and just get any of the generic objects later in case someMethod() ends up needing them. I hope there's some clean way to achieve this.
Alright, looks like my second solution would work after all. What I was worried about but didn't know the word for was circular dependencies. It turns out, Node.js handles those rather well and require only imports a file once, so it doesn't run again if a file is executed by a file it itself already required.
Tested it like this:
// test1.js
function callTest1() { console.log('test1.js checking in: ' + Date.now()); }
exports.callTest = callTest1;
console.log('test1.js is executing');
const test2 = require('./test2');
test2.callTest();
// test2.js
function callTest2() { console.log('test2.js checking in: ' + Date.now()); }
exports.callTest = callTest2;
console.log('test2.js is executing');
const test1 = require('./test1');
test1.callTest();
Result when executing test1.js:
test1.js is executing
test2.js is executing
test1.js checking in: 1643405381177
test2.js checking in: 1643405381178
What happens is the following:
test1.js defines callTest1() and adds it to its module.exportstest1.js logs test1.js is executingtest1.js requires test2.js, which is now executedtest2.js defines callTest2() and adds it to its module.exportstest2.js logs test2.js is executingtest2.js requires test1.js, but it was already executed, so this doesn't happen againtest2.js calls test1.callTest(), which logs test1.js checking in: 1643405381177test1.js finishes executing test2.jstest1.js calls test2.callTest(), which logs test2.js checking in: 1643405381178So, looks like I can just place my 'getters' in my index.js file. I'll just have to be mindful of the order in which files are loaded, so I don't require index.js before its getters are added to module.exports. I'll leave this question unanswered for now, in case someone does show up with a cleaner solution.