matthiasdv matthiasdv - 1 year ago 53
Node.js Question

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:

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


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


// configuration ===============================================================


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

// launch ======================================================================


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?

Answer Source

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.