6

开始学习 node.js 和 backbone.js,并使用 TodoMVC 示例作为我的指南。有几个部分我很难理解。见下文。

这是 app.js。

var express = require('express')
  , http = require('http')
  , mongoose = require('mongoose')
  , models = require('./models')
  , routes = require('./routes')
  , app = express();

app.configure(function () {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(require('stylus').middleware({ src: __dirname + '/public' }));
  app.use(express.static(__dirname + '/public'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
});

app.configure('development', function () {
  app.use(express.errorHandler());
});

routes.init(app);


mongoose.connect("127.0.0.1", "todomvc", 27017);

http.createServer(app).listen(3000);

console.log("Express server listening on port 3000");

这是./models:

var mongoose = require('mongoose'),

  TodoSchema = new mongoose.Schema({
    title: { 'type': String, 'default': 'empty todo...' },
    order: { 'type': Number },
    done: { 'type': Boolean, 'default': false }
  });

module.exports = mongoose.model('Todo', TodoSchema);

最后,安迪,这里是 ./routes:

(function (exports) {

  "use strict";

  var mongoose = require('mongoose')
    , crudUtils = require('../utils/crudUtils')
    , Todo = mongoose.model('Todo');

  function index(req, res) {
    res.render('index', { 'title': 'Backbone.js, Node.js, MongoDB Todos' });
  }

  exports.init = function (app) {
    app.get('/', index);
    crudUtils.initRoutesForModel({ 'app': app, 'model': Todo });
  };

}(exports));

所以我的问题是,路由模块中的 mongoose.model('Todo') 中的“Todo”模型如何在此范围内可用?我看到模型模块正在导出 mongoose.model('Todo', TodoSchema); 所以我必须相信路由模块是如何访问它的,但我不知道为什么。我错过了什么?我有一种感觉,在这种情况下,它只是不完全理解范围。另外,我不确定路由功能匿名的原因。

非常感谢!

4

2 回答 2

8

这是从 Node 和 Mongoose 开始时要处理的更令人困惑的事情之一。

当您require('mongoose')第一次使用时,它会创建一个Mongoose 的单例实例 - 以后每次需要它时都会返回相同的实例。

这使得它非常容易使用,但是在开始时有点难以理解的“魔法”。

这意味着当您调用mongoose.connect("127.0.0.1", "todomvc", 27017);app.js 时,它会创建一个与应用程序持续存在的连接。

这也意味着mongoose.model('Todo', TodoSchema);使 Todo 模型在任何其他调用require('mongoose'), via的范围内可用mongoose.model('Todo')。如上例所示,这可以在另一个文件的顶部进行 var'd require,或者在回调中间需要它的那一刻。

这就是您将 Todo 模型放入您的 routes.js 的方式,并且有一个很好的理由确保告诉 Mongoose 您的模型是您在应用程序中做的第一件事。

回答您关于理解范围的问题;您实际上拥有的每个文件require都有自己的范围,并且除了进程之类的全局对象外,无权访问任何内容。你必须拥有require你想要使用的所有东西,并且只能通过调用函数或创建通过exports对象公开的类来传递变量。

因此,对于上面的实际示例,从models.js 导出模型没有任何好处,因为它随后没有在需要models.js 的app. 中引用。正是 routes.js 中的这些行使 Todo 模型可用:

var mongoose = require('mongoose')
, Todo = mongoose.model('Todo'); // returns the Todo model that was registered by models.js

这就是 Todo 在这条线上的存在方式:

crudUtils.initRoutesForModel({ 'app': app, 'model': Todo });

将路由包装在匿名函数中也没有任何好处(据我所知),因为这本质上是由require.

于 2012-10-24T03:19:45.650 回答
0

您将要查看 Express。

Express 是一个最小且灵活的 node.js Web 应用程序框架,为构建单页和多页以及混合 Web 应用程序提供了一组强大的功能。

您复制和粘贴的很多内容都是使用 Express Scaffold - 所以很多都是为您预先构建的,您可以在此处查看: http: //expressjs.com/

我希望这能为您指明正确的方向。

于 2012-10-24T02:57:03.803 回答