matthiasdv
matthiasdv

Reputation: 1166

Scoping issue using require() in node JS

I set up a web server using node JS and the Express module. My code is as follows :

file tree:

/src
 |
 +-- server.js
 +-- /app
     |
     +-- routes.js

server.js

// set up ======================================================================
var express  = require('express');
var app      = express();
var mongoose = require('mongoose');

...

// configuration ===============================================================
mongoose.connect(configDB.url);

...

// routes ======================================================================
require('./app/routes.js')(app, passport);

// launch ======================================================================
app.listen(port);

routes.js

    module.exports = function(app, passport) {
        app.get('/some-route', function(req, res) {
            // this line bugs out
            var User = mongoose.model('User', userSchema);
        });
    };

My question:

Calling mongoose.model() in routes.js throws the following error

ReferenceError:mongoose is not defined

Why is mongoose not known in this context when I've included it in server.js, the file in which routes.js is being included? Should I require() mongoose again in routes.js? What am I missing here?

Upvotes: 0

Views: 712

Answers (2)

Stavros Zavrakas
Stavros Zavrakas

Reputation: 3053

The modules that are included is on a file are not visible on another file. Here you can find a list of the global objects that are available on every module that you create:

https://nodejs.org/api/globals.html

All the other objects/variables that you define within a file they are defined within the context of this file. Otherwise, this could create huge problems with variables that overwrite other variables in other files and creating a mess within a project. You can think of a file like a function that includes all your code and everything that is defined in there, is not available to the global namespace.

In your case, you have to require('mongoose') in the files that you need it, and it is built like that so that can maintain the existing connection to the database.

Upvotes: 1

jfriend00
jfriend00

Reputation: 707158

Variables defined within a module are local only to that module. They are not in the scope of other modules that you require() in with that module. That's why mongoose is not know to your routes module. The require() operation does not insert the code right into the calling module. Instead, it loads that code from disk and then inserts it into its own function and calls that function. This gives each loaded module its own independent scope. It is not inserted into the current scope.

In cases like this, you have several choices:

  1. Require() in the mongoose module again in routes. This is generally preferred when possible because this makes the routes module more self sufficient and easier to reuse as it requires in the things it needs.

  2. Pass in the object you want to share with the routes constructor just like you are passing in app and passport. This method is preferred when the item needed by the other module is not just the result of a simple module load. For example, app is the result of calling a constructor function so the only way for another module to use the same app instance is for you to pass it.

  3. You can have routes call out to some other module to request information. For example, since you've already passed the app object to routes, you could put the mongoose object as either a property on the app object so it could be referenced that way or you could add a method to the app object to retrieve it via the method call.

In this case, since mongoose is just a cached module, it probably makes the most sense to just require() it in again, but any one of the three methods above would work.

Upvotes: 1

Related Questions