在 Express 項目中使用 Waterline

jopen 9年前發布 | 13K 次閱讀 Express 前端技術

在上一篇Node.js ORM 數據操作中間件 Waterline 中,我們介紹了 Waterline 的功能與特點,這篇文章中我們將用一個實例 waterline-sample (GithubCoding.NET),來看看在 Express 項目中如何使用 Waterline。

要在項目中使用 Waterline ,無非是解決如何配置,在什么時機初始化,怎樣組織所有的數據集合,以及在控制器中怎么調用 Waterline 中的數據集合這幾個問題。

項目的功能與結構

這個示例項目中,將會實現兩個關于 Post 的 API ,添加和獲取列表的接口,功能比較簡單,但代碼的組織,依然遵循模塊化和 MVC 的設計原則,主要的文件和目錄如下:

</span>
|-- app
|   |-- controllers
|   |   `-- post.server.controller.js
|   |-- models
|   |   `-- post.server.model.js
|   `-- routes
|       `-- post.server.routes.js
|-- config
|   |-- config.js
|   |-- env
|   |   `-- development.js
|   |-- express.js
|   `-- waterline.js
|-- app.js
|-- bin
|   `-- www
`-- package.json

其中,config目錄存儲基本配置、 Express 配置和 Waterline 的配置文件,其中的env目錄存儲根據環境而不同的基本配置。app目錄下的三個文件夾,分別按 MVC 的結構組織 Waterline 的 Collections ,Expresss 的控制器以及路由文件。根目錄下的app.js將使用config/express.js中的配置來生成 Express 的實例,而入口文件bin/www則完成 Waterline 的初始化和啟動 Express 實例的端口監聽。

數據集合的組織

所有的數據集合,全部組織在app/models目錄中,直接使用module.exports來將Waterline.Collections實例導出,以便在 Waterline 的配置文件中調用。

</span>
var Waterline = require('waterline');

module.exports = Waterline.Collection.extend({ identity: 'post', connection: 'mongo', schema: true, attributes: { title: { type: 'string', required: true }, content: 'string', createTime: 'date', lastModifyTime: 'date' }, beforeCreate: function(v, cb){ v.createTime = new Date(); return cb(); }, print: function(v) { console.log('\tTitle:', v.title, 'create at:', v.createTime); console.log('\tContent:', v.content); } });</pre>

這里也演示了如何定義生命周期回調和自定義的方法。

配置

配置里主要是生成 Waterline 的實例,并加載上面的數據集合配置文件。

</span>
var Waterline = require('waterline');
var mongoAdapter = require('sails-mongo');
var config = require('./config');

// models var Post = require('../app/models/post.server.model');

var orm = new Waterline(); var wlconfig = { adapters: { 'default': mongoAdapter, mongo: mongoAdapter }, connections: { 'mongo': { adapter: 'mongo', url: config.mongo } } }; orm.loadCollection(Post);

exports.orm = orm; exports.config = wlconfig;</pre>

這里使用的是exports來導出,因為我們有兩個值需要導出,一個是 Waterline 的實例,另外一個是 Waterline 的初始化配置。這在初始化的時候會用到。

初始化

初始化是在bin/www里完成的,原因是保證 Express 啟動監聽,必須在 Waterline 的成功初始化之后進行。

</span>
var app = require('../app');
var config = require('../config/config');
var waterline = require('../config/waterline');

waterline.orm.initialize(waterline.config, function(err, models){ if(err) { console.log('waterline initialize failed, err:', err); return; } console.log('waterline initialize success.');

app.set('models', models.collections);

app.listen(config.port, function(){ console.log('Express listening on port:', config.port); }); });</pre>

初始化是直接使用 Waterline 實例的intialize()方法,需要傳入對應的配置,這兩個都是在waterline.js配置文件中導出的。為了方便我們在控制器代碼中調用 Waterline 的數據集合,這里先將它加入到 Express 實例的配置列表中。

在 Express 控制器中使用 Waterline 數據集合

由于 Waterline 的初始化過程是異步的,所以我們沒有辦法直接使用module.exports或exports方法來導出它的實例,也就無法直接以 JavaScript 模塊化的方式調用它實例中的數據集合。這里將借助 Express 的實例,來在控制器代碼中使用它。

但實際上,在控制器代碼中,也是沒有辦法直接訪問 Express 的實例的,所以這里我們在 Express 的配置里,增加一個中間件,將附加在 Express 實例上的數據集合,再加入到 Express 請求對象中,這樣便可以在控制器代碼中通過請求對象來訪問 Waterline 實例的數據集合了。當然,加到響應對象也可以。

</span>
var express = require('express');
var waterline = require('./waterline');

module.exports = function(){ console.log('express initialing...'); var app = express(); // ... app.use(function(req, res, next){ req.models = app.get('models'); next(); });

require('../app/routes/post.server.routes')(app); // ... return app; };</pre>

在控制器里,便可以通過請求對象的models成員來調用了。

module.exports = {
  list: function(req, res, next){
    var page = parseInt(req.query.page, 1) ? parseInt(req.query.page, 1) : 1;
    var limit = parseInt(req.query.limit, 1) ? parseInt(req.query.limit, 1) : 1;
    req.models.post.find().paginate({page: page, limit: limit}).exec(function(err, docs){
      res.json(docs);
    });
  }
};

雖然也可以通過全局變量來調用數據集合,不過在有其它辦法的情況下,還是盡量不要使用全局變量吧。

來自:http://chensd.com/2015-10/Use-Waterline-in-Express-project.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!