ddms(基于 Express 的表单管理系统)源码学习

ddms是基于express的一个表单管理系统,今天抽时间看了下它的代码,其实算不上源码学习,只是对它其中一些小的开发技巧做一些记录,希望以后在项目开发中能够实践下。

  • 数据层封装
    • 模块只对外暴露model,由业务层完成具体数据操作;
    • 利用mongoose的schema的static属性,扩展常用、基础的操作
var form = new Schema({
  user: {type: ObjectId, ref: 'User'},
  project: {type: ObjectId, ref: 'Project'},
  sid: {type: String, unique: true,'default': shortid.generate },
  title: {
    type: String,
    required: true,
    default: 'New Form'
  },
  desc: String,
  createDateTime: {
    type: Date,
    default: Date.now
  },
  updateDateTime: {
    type: Date,
    default: Date.now
  },
  schemata: Mixed
});

form.static({
  list: function (callback) {
    return this.find()
      .populate('user',{_id: 1,name: 1,email: 1,role: 1})
      .populate('project',{_id: 1,name: 1,desc: 1})
      .sort({_id: -1})
      .exec(callback)
  },
  listByProjectId: function (projectid,callback) {
    return this.find({project: projectid})
      .populate('user',{_id: 1,name: 1,email: 1,role: 1})
      .populate('project',{_id: 1,name: 1,desc: 1})
      .sort({_id: -1})
      .exec(callback);
  }
});

module.exports = mongoose.model('Form', form);
  • 充分利用schema type特性
    • 充分利用schema type的例如gettersettervalidate等 参考:http://mongoosejs.com/docs/2.7.x/docs/schematypes.html。可以将原本业务层的很多处理直接交给mongodb.
var userSchema = new Schema({
  email: {
    type: String,
    required: true, //需要校验
  //给字段存储前线全部小写处理 set: function (value) {
return value.trim().toLowerCase() },
  //校验的方法 validate: [ function (email) {
return (email.match(/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/i) != null) }, 'Invalid email' ] }, //。。。。 twitter: Mixed });
  • 利用ref来实现join,可以存在多个,如下:
var form = new Schema({
  user: {type: ObjectId, ref: 'User'},
  project: {type: ObjectId, ref: 'Project'},
  sid: {type: String, unique: true,'default': shortid.generate },
form.static({
  list: function (callback) {
    return this.find()
      .populate('user',{_id: 1,name: 1,email: 1,role: 1})
      .populate('project',{_id: 1,name: 1,desc: 1})
      .sort({_id: -1})
      .exec(callback)
  },
  listByProjectId: function (projectid,callback) {
    return this.find({project: projectid})
      .populate('user',{_id: 1,name: 1,email: 1,role: 1})
      .populate('project',{_id: 1,name: 1,desc: 1})
      .sort({_id: -1})
      .exec(callback);
  }
});
  • 充分利用app.use
    • app.use在express中类似servlet里的filter,属于一种过滤器,它会在每个http请求中被调用
    • ddms通过app.use向req对象中添加model
//app.js中
app.use(function (req, res, next) {
  if (!models.User) return next(new Error("No models."));
  req.models = models;
  return next();
});

//route.js中
exports.showListByProjectId = function (req, res, next) {
  var pid = req.params.projectid;
  var pp = Promise.resolve( req.models.Project.findOne({_id: pid}) );
  var fp = Promise.resolve( req.models.Form.listByProjectId(pid) );

  Promise.all([pp,fp])
    .then(function(docs){
      res.render('forms/list', {project: docs[0],forms: docs[1]});
    }).catch(function (error) {
      return next(error);
    });
};
  • 采用bluebird的promise库做同步

之前一直用async,看了下promise,感觉非常清爽,同上例代码

  • 利用app.get的多callback实现中间件的效果,如下:
app.get('/formdatas/:formid', authorize.editor, routes.formData.showList);
app.get('/formdatas/create/:formid', authorize.editor, routes.formData.showCreateData);
app.post('/formdatas/create/:formid', writeLog, authorize.editor, routes.formData.createData);
app.get('/formdatas/update/:id', authorize.editor, routes.formData.showUpdateData);
app.post('/formdatas/update/:id', writeLog, authorize.editor, routes.formData.updateData);
app.get('/formdatas/delete/:id', writeLog, authorize.editor, routes.formData.deleteData);
app.get('/formdatas/csv/:formid', writeLog, authorize.editor, routes.formData.getCSV);
原文地址:https://www.cnblogs.com/Fredric-2013/p/4618909.html