0

I have a separate js file that exports the mongoDB connection so the other files can use it without creating a new connection. (one of mongoDB's best practices)

mongoClient.js (returns the connected client)

// Defining the MongoClient

const { MongoClient } = require("mongodb");
const mongo = new MongoClient(
    process.env.MONGO_AUTH,
    {
        useNewUrlParser: true,
        useUnifiedTopology: true,
    }
);

mongo.connect((err, result) => {

    // result == mongo ✅
    module.exports = result;

    console.log(module.exports); // When the script is run alone, it works. When it's required somewhere else, nothing is logged (is it executed?)
    
    process.on("SIGINT", function () {
        mongo.close();
    });

});

As written above, module.exports seems to work. When I require it in another file, there is no export found:

in other files

const mongo = require("../mongoClient");
console.log(mongo); // {}

I've heard about something called cyclic dependencies. It seems to correspond with my case, with one difference... there is none. mongoClient.js's only dependency is the mongodb node_module (which, besides, is nowhere else in the other files). Then, where is the mistake, and how could I solve it?

deb
  • 6,671
  • 2
  • 11
  • 27
  • ive never seen `module.exports` nested in a callback, never tried but I would presume it doesn't work, but won't error out by js, but maybe a linter. Callbacks in this situation are horrid, id suggest make a class and use the constructor to initialise the instance in async/await.. just like this answer: https://stackoverflow.com/a/59601215/661872 (but with better error handling) – Lawrence Cherone Aug 01 '20 at 15:35

2 Answers2

0

Javascript evaluate modules when the app is initialized. You are setting the module.exports asynchronously so it's not available as a module.

Instead of the above code, you can do like below:

const { MongoClient } = require("mongodb");
const mongo = new MongoClient(
    process.env.MONGO_AUTH,
    {
        useNewUrlParser: true,
        useUnifiedTopology: true,
    }
);

let mongoInstance;

mongo.connect((err, result) => {

    // result == mongo ✅
    mongoInstance = result;
    
    process.on("SIGINT", function () {
        mongo.close();
    });

});

module.exports = () => mongoInstance;

And in other files you use it:

const mongo = require("../mongoClient");
console.log(mongo());

Note:

I think you are using Nodejs server. Usually the server should be up after the database connection is established successfully.

critrange
  • 5,652
  • 2
  • 16
  • 47
  • `console.log(mongo())` returns `undefined`. I'm not trying to get a function but a variable in module.exports. The problem remains the same: `mongoInstance` is exported before it has been (asynchronously) defined – deb Aug 02 '20 at 13:15
  • that's what i mentioned in Note, you should start your server after the instance is initiated – critrange Aug 02 '20 at 14:32
0

You can make your db connection global and have access to it in the entire application.

const { MongoClient } = require("mongodb");
const mongo = new MongoClient(
    process.env.MONGO_AUTH,
    {
        useNewUrlParser: true,
        useUnifiedTopology: true,
    }
);


mongo.connect((err, result) => {

    // result == mongo ✅
     global.mongo = result;
        
    process.on("SIGINT", function () {
        mongo.close();
    });

});
console.log(global.mongo);

and can access it in other files

deb
  • 6,671
  • 2
  • 11
  • 27
  • This `global.mongo` idea is very good! Unfortunately, if a request is received before it has been defined, it would generate an error. I could set a timeout or a `.then(() => );`, but it wouldn't be very nice. – deb Aug 02 '20 at 13:38
  • You have to initialise your db in starting. make a socket connection and dont proceed until you db connection is not successful. –  Aug 02 '20 at 13:42