Skip to content Skip to sidebar Skip to footer

Behavior Of Require In Node.js

I currently have a database connection module containing the following: var mongodb = require('mongodb'); var client = mongodb.MongoClient; client.connect('mongodb://host:port/dbna

Solution 1:

There are 3 key points to understand here and then I will explain them in detail.

  1. module.exports is an object and objects are passed by copy-of-reference in JavaScript.
  2. require is a synchronous function.
  3. client.connect is an asynchronous function.

As you suggested, it is a timing thing. node.js cannot know that module.exports is going to change later. That's not it's problem. How would it know that?

When require runs, it finds a file that meets its requirements based on the path you entered, reads it and executes it, and caches module.exports so that other modules can require the same module and not have to re-initialize it (which would mess up variable scoping, etc.)

client.connect is an asynchronous function call, so after you execute it, the module finishes execution and the require call stores a copy of the module.exports reference and returns it to users.js. Then you set module.exports = db, but it's too late. You are replacing the module.exports reference with a reference to db, but the module export in the node require cache is pointing to the old object.

It's better to define module.exports as a function which will get a connection and then pass it to a callback function like so:

var mongodb = require("mongodb");
var client = mongodb.MongoClient;

module.exports = function (callback) {
    client.connect('mongodb://host:port/dbname', { auto_reconnect: true },
          function(err, db) {
             if (err) {
                console.log(err);
                callback(err);
             } else {
                // export db as member of exports
                callback(err, db);
             }
          }
    )
};

Warning: though it's outside the scope of this answer, be very careful with the above code to make sure you close/return the connections appropriately, otherwise you will leak connections.


Solution 2:

Yes, dbConnection.db is undefined because the connection is made asynchronously which means by definition the node code just continues to execute without waiting for the DB connection to be established.

shouldn't require() wait until the module finishes running its code before assigning the value of module.exports?

Nope, it just doesn't work that way. require is for code that is always there. Database connections aren't code and aren't always there. Best not to confuse these two types of resources and how to reference them from you program.


Solution 3:

shouldn't `require() wait until the module finishes running its code before assigning the value of module.exports?

module.exports.db is setting in callback, this operation is async, so in user.js you can't get db.collection. It will be better to add collections in connect callback.

You can use this answer to change you code and use shared connection in other modules.


Post a Comment for "Behavior Of Require In Node.js"