我应该如何构建我的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:无法调用undefined(routes.js)的方法’userlist’.
解决方法:
有或多或少的两个轴来组织您的代码.根据模块的层功能(数据库,模型,外部接口)或按功能/上下文(用户,订单)组织代码.大多数(MVC)应用程序使用功能组织架构,该架构更易于处理,但不会泄露应用程序的目的或意图.
除了组织代码之外,功能层应该尽可能地分离.
代码中的功能层是
>在应用程序中抽象数据和行为的模型
>构成应用程序外部接口的路由.路线不是应用程序!
>引导代码(server.js),负责启动和连接应用程序的各个部分
上面的代码库似乎使用了功能组织架构,这很好.使用模块目录对我来说并没有多大意义,似乎是多余的.所以我们有一个像这样的架构
|- server.js
|+ users
|- schema.js
|- routes.js
现在让我们打破一些依赖…
schema.js
代码的模式/模型部分不应该依赖于代表应用程序接口的应用程序.此版本的schema.js导出模型,不需要将快速应用程序或mongoose实例传递到某种工厂函数:
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;
此代码省略了获取一个用户和创建新用户的实现,因为这些应该与用户列表非常相似.用户列表路由现在只负责在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路径下安装哪个版本的路由.