2014-04-09 32 views
3

我應該如何構建我的快速/貓鼬應用程序,以便可以使用我的模式,模型,路線以及在這些路線被擊中時調用的函數?Express/Mongoose應用程序的結構

server.js

// setup 
var express = require("express"); 
var app = express(); 
var mongoose = require("mongoose"); 
app.db = mongoose.connect('mydb')); 

// this is the bit I am not sure about 
var UserSchema = require('./modules/users/schema')(app, mongoose); 
var routes = require('./modules/users/routes')(app, mongoose, UserSchema); 

// listen 
app.listen(3000); 

模塊/用戶/ schema.js

exports = module.exports = function(app, mongoose) 
{ 
    var UserSchema = mongoose.Schema(
    { 
     username: { type: String, required: true }, 
     password: { type: String } 
    }); 

    var UserModel = mongoose.model('User', UserSchema, 'users'); 

    // it looks like this function cannot be accessed 
    exports.userlist = function(db) 
    { 
     return function(req, res) 
     { 
      UserModel.find().limit(20).exec(function(err, users) 
      { 
       if(err) return console.error(err); 
       res.send(users);  
      }); 
     }; 
    }; 
} 

模塊/用戶/ routes.js

function setup(app, mongoose, UserSchema) 
{ 
    var db = mongoose.connection; 

    // get all users 
    app.get('/api/v1/users', UserSchema.userlist(db)); // this function cannot be accessed 

    // get one user 
    app.get('/api/v1/users/:id', UserSchema.userone(db)); 

    // add one new user 
    app.post('/api/v1/users', UserSchema.addone(db)); 
} 

// exports 
module.exports = setup; 

PS:我得到的錯誤是app.get('/api/v1/users', UserSchema.userlist(db)); TypeError: Cannot call method 'userlist' of undefined (routes.js)。

回答

0

在您的應用程序結構中,您將數據庫邏輯與高速路由處理混合並將快速應用程序變量傳遞給模型。我會避免混合這兩個在一起,你也可以看看這個結構https://gist.github.com/fwielstra/1025038

2

看看我的express_code_structure示例回購,以瞭解關於模塊文件系統組織的建議。

但是,上面的代碼示例是主要的MVC違規。不要將app實例傳遞給您的模型。不要讓你的模型知道任何req對象或HTTP服務。模型:數據結構,完整性,持久性,業務邏輯,沒有別的。路線應該從模型中完全分開的.js文件中定義。

0

我最近遇到了一個教程,它生成了this sample app,它有我見過的最好的結構之一。在/ server/models /下查看Mongoose如何設置。

0

我寫了一個模塊orm-model,它可以幫助您在nodejs應用程序中構建模型。

8

有或多或少的兩個軸來組織你的代碼。根據模塊(數據庫,模型,外部接口)的層功能或者它們所作用的功能/上下文(用戶,訂單)組織代碼。大多數(MVC)應用程序使用的功能性組織架構更易於處理,但不會揭示應用程序的目的或意圖。

除了組織代碼功能層之外,應該儘可能分離。

在代碼功能層是

  • 模型抽象數據和行爲在應用程序
  • 路線構成應用程序的一個外部接口。路線是不是的申請!
  • 啓動代碼(server.js),負責啓動並連接您的應用程序

上面的代碼庫似乎使用功能的組織架構,這是很好的部分。使用modules目錄對我來說並不合理,似乎是多餘的。因此,我們有一個模式在某種程度上是這樣

|- server.js 
|+ users 
|- schema.js 
|- routes.js 

現在,讓我們打破某些依賴...

schema.js

代碼的架構/模型部分不應該依賴於應用程序代表您的應用程序的接口。這的schema.js版本的出口型號,並不需要一個明確的應用程序或貓鼬實例來傳遞到某種廠功能:

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 

var UserSchema = Schema({ 
    username: { type: String, required: true }, 
    password: { type: String } 
}); 

// Use UserSchema.statics to define static functions 
UserSchema.statics.userlist = function(cb) { 
    this.find().limit(20).exec(function(err, users) 
    { 
     if(err) return cb(err); 

     cb(null, users); 
    }); 
}; 

module.exports = mongoose.model('User', UserSchema, 'users'); 

顯然,這丟了原始文件的app.send功能。這將在routes.js文件中完成。您可能會注意到我們不再導出/api/v1/users,而是/。這使得快速應用程序更加靈活,並且自成一體。

參見this post for a article explaining express routers in detail

var express = require('express'); 
var router = express.Router(); 
var users = require('./schema'); 

// get all users 
router.get('/', function(req, res, next) { 
    users.userlist(function(err, users) { 
     if (err) { return next(err); } 

     res.send(users); 
    }); 
}); 

// get one user 
router.get('/:id', ...); 

// add one new user 
router.post('/', ...); 

module.exports = router; 

此代碼省略實現用於獲取一個用戶,並創建新用戶,因爲這些工作應該頗爲相似userlist。現在,userlist路由具有在HTTP和您的模型之間進行調解的單一責任。

最後一部分是在server.js配線/啓動代碼:

// setup 
var express = require("express"); 
var app = express(); 
var mongoose = require("mongoose"); 

mongoose.connect('mydb'); // Single connection instance does not need to be passed around! 

// Mount the router under '/api/v1/users' 
app.use('/api/v1/users', require('./users/routes')); 

// listen 
app.listen(3000); 

因此,該模型/架構的代碼不依賴於應用程序接口代碼,該接口有一個明確的責任和接線碼在server.js中可以決定在哪個URL路徑下安裝哪個版本的路由器。