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