在节点 JS 中使用 require() 的范围问题
Scoping issue using require() in node JS
我使用节点 JS 和 Express 模块设置了一个网络服务器。我的代码如下:
文件树:
/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);
});
};
我的问题:
在routes.js中调用mongoose.model()会抛出以下错误
ReferenceError:mongoose is not defined
当我将 mongoose 包含在包含 routes.js 的文件 server.js 中时,为什么在此上下文中不为人所知?我应该在 routes.js 中再次要求()猫鼬吗?我在这里错过了什么?
模块中定义的变量仅对该模块是本地的。它们不在您 require()
与该模块一起使用的其他模块的范围内。这就是为什么 mongoose
不为您的路线模块所知。 require()
操作不会将代码直接插入到调用模块中。相反,它从磁盘加载该代码,然后将其插入到自己的函数中并调用该函数。这为每个加载的模块提供了自己独立的范围。它没有插入到当前范围。
在这种情况下,您有多种选择:
Require()
再次在路由中的 mongoose 模块中。这在可能的情况下通常是首选,因为这使得路由模块更加自给自足并且更容易重用它需要的东西。
像传入app
和passport
一样,传入要与路由构造函数共享的对象。当其他模块需要的项目不仅仅是简单模块加载的结果时,首选此方法。例如,app
是调用构造函数的结果,因此另一个模块使用相同 app
实例的唯一方法是让您传递它。
您可以让路由调用其他模块以请求信息。例如,由于您已经将 app
对象传递给路由,您可以将 mongoose
对象作为 属性 放在 app
对象上,以便可以引用它这样或者您可以向 app
对象添加一个方法以通过方法调用检索它。
在这种情况下,由于 mongoose
只是一个缓存模块,因此再次 require()
可能最有意义,但上述三种方法中的任何一种都可以。
包含在一个文件中的模块在另一个文件中不可见。您可以在此处找到您创建的每个模块上可用的全局对象列表:
https://nodejs.org/api/globals.html
您在文件中定义的所有其他 objects/variables 它们是在该文件的上下文中定义的。否则,这可能会产生巨大的变量问题,这些变量会覆盖其他文件中的其他变量,并在项目中造成混乱。您可以将文件想象成一个函数,其中包含您的所有代码和其中定义的所有内容,但对全局命名空间不可用。
在你的情况下,你必须 require('mongoose')
在你需要的文件中,它是这样构建的,以便可以保持与数据库的现有连接。
我使用节点 JS 和 Express 模块设置了一个网络服务器。我的代码如下:
文件树:
/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);
});
};
我的问题:
在routes.js中调用mongoose.model()会抛出以下错误
ReferenceError:mongoose is not defined
当我将 mongoose 包含在包含 routes.js 的文件 server.js 中时,为什么在此上下文中不为人所知?我应该在 routes.js 中再次要求()猫鼬吗?我在这里错过了什么?
模块中定义的变量仅对该模块是本地的。它们不在您 require()
与该模块一起使用的其他模块的范围内。这就是为什么 mongoose
不为您的路线模块所知。 require()
操作不会将代码直接插入到调用模块中。相反,它从磁盘加载该代码,然后将其插入到自己的函数中并调用该函数。这为每个加载的模块提供了自己独立的范围。它没有插入到当前范围。
在这种情况下,您有多种选择:
Require()
再次在路由中的 mongoose 模块中。这在可能的情况下通常是首选,因为这使得路由模块更加自给自足并且更容易重用它需要的东西。像传入
app
和passport
一样,传入要与路由构造函数共享的对象。当其他模块需要的项目不仅仅是简单模块加载的结果时,首选此方法。例如,app
是调用构造函数的结果,因此另一个模块使用相同app
实例的唯一方法是让您传递它。您可以让路由调用其他模块以请求信息。例如,由于您已经将
app
对象传递给路由,您可以将mongoose
对象作为 属性 放在app
对象上,以便可以引用它这样或者您可以向app
对象添加一个方法以通过方法调用检索它。
在这种情况下,由于 mongoose
只是一个缓存模块,因此再次 require()
可能最有意义,但上述三种方法中的任何一种都可以。
包含在一个文件中的模块在另一个文件中不可见。您可以在此处找到您创建的每个模块上可用的全局对象列表:
https://nodejs.org/api/globals.html
您在文件中定义的所有其他 objects/variables 它们是在该文件的上下文中定义的。否则,这可能会产生巨大的变量问题,这些变量会覆盖其他文件中的其他变量,并在项目中造成混乱。您可以将文件想象成一个函数,其中包含您的所有代码和其中定义的所有内容,但对全局命名空间不可用。
在你的情况下,你必须 require('mongoose')
在你需要的文件中,它是这样构建的,以便可以保持与数据库的现有连接。