将DB引用到路由中对我的Node / Express项目不起作用

时间:2013-01-04 00:05:04

标签: node.js express node-mongodb-native

我正在使用node + express创建一个简单的REST API,并尝试将路由逻辑与db逻辑分开。我在从路线访问数据库时遇到问题。

这是我的server.js代码:

var express = require('express')
  , path = require('path')
  , http = require('http')
  , mongo = require('mongodb');

// Configure Express app
var app = express();
app.configure(function () {
    app.set('port', process.env.PORT || 3000);
    app.use(express.logger('dev'));  /* 'default', 'short', 'tiny', 'dev' */
    app.use(express.bodyParser()),
    app.use(express.static(path.join(__dirname, 'public')));
});

// Configure DB
var Server = mongo.Server
  , Db = mongo.Db
  , BSON = mongo.BSONPure
  , server = new Server('localhost', 27017, {auto_reconnect: true})
  , db = new Db('mydb', server, {safe: true});

// Open DB to see if we need to populate with data
db.open(function(err, db) {
  if(!err) {
    console.log("Connected to 'mydb' database");
    var Post = require('./routes/posts')
      , post = new Post(db);

    // Set the routes
    app.get('/:org/posts', post.find);
    app.get('/:org/posts/:id', post.get);
    app.post('/:org/posts', post.add);
    app.put('/:org/posts/:id', post.update);
    app.delete('/:org/posts/:id', post.remove);

    // Fire up the server
    http.createServer(app).listen(app.get('port'), function () {
      console.log("Express server listening on port " + app.get('port'));
    });
  }
});

这是post.js文件中的逻辑:

var Post = function(db) {
  this.db = db;
};

Post.prototype.get = function(req, res) {
  var id = req.params.id;
  var org = req.params.org;
  var db = this.db;

  console.log('Retrieving post: ' + id + ' from org: ' + org);
  db.collection('ads', function(err, collection) {
    collection.findOne({'_id':new BSON.ObjectID(id), 'org':org}, function(err, item) {
      res.send(item);
    });
  });
};

Post.prototype.find = function(req, res) {
  var org = req.params.org;
  var db = this.db;

  console.log('Finding posts for org: ' + org);
  db.collection('posts', function(err, collection) {
    collection.find({'org':org}).toArray(function(err, items) {
      res.send(items);
    });
  });
};

Post.prototype.add = function(req, res) {
  var org = req.params.org;
  var post = req.body;
  var db = this.db;

  console.log('Adding post: ' + JSON.stringify(post) + ' for org: ' + org);
  db.collection('posts', function(err, collection) {
    collection.insert(post, {safe:true}, function(err, result) {
      if (err) {
        res.send({'error':'An error has occurred'});
      } else {
        console.log('Success: ' + JSON.stringify(result[0]));
        res.send(result[0]);
      }
    });
  });
};

Post.prototype.update = function(req, res) {
  var id = req.params.id;
  var org = req.params.org;
  var post = req.body;
  var db = this.db;

  delete post._id;
  console.log('Updating post: ' + id + ', org: ' + org);
  console.log(JSON.stringify(post));
  db.collection('posts', function(err, collection) {
    collection.update({'_id':new BSON.ObjectID(id)}, post, {safe:true}, function(err, result) {
      if (err) {
        console.log('Error updating post: ' + err);
        res.send({'error':'An error has occurred'});
      } else {
        console.log('' + result + ' document(s) updated');
        res.send(post);
      }
    });
  });
};

Post.prototype.remove = function(req, res) {
  var id = req.params.id;
  var org = req.params.org;
  var db = this.db;

  console.log('Deleting post: ' + id + ', org: ' + org);
  db.collection('posts', function(err, collection) {
    collection.remove({'_id':new BSON.ObjectID(id), 'org':org}, {safe:true}, function(err, result) {
      if (err) {
        res.send({'error':'An error has occurred - ' + err});
      } else {
        console.log('' + result + ' document(s) deleted');
        res.send(req.body);
      }
    });
  });
};

module.exports = Post;

我认为post对象会保留db引用,以便在从路由调用时使用,但是我收到以下错误:

TypeError: Cannot call method 'collection' of undefined
    at Post.find (../routes/posts.js:23:6)

有人能指出我正确的方向吗?非常感谢

2 个答案:

答案 0 :(得分:6)

试试这种方式。自从我不久前在Stack Overflow上发现它以来,它成了我最喜欢的编写模块的方式。

server.js:

...    
var Post = require('./routes/posts')(db);
...

posts.js:

...
module.exports =function(db) {
        var module = {};

         module.get = function(req, res){
            ...
            /* db should be accessible here */

         }

         return module;
}

答案 1 :(得分:1)

当您正在注册的Express路由处理程序调用{​​{1}}方法时,post对象将丢失为this。您需要Post bind实例的方法,以便无论Express如何调用它们,post都将是您的this。像这样:

post