[node.js]express+mongoose+mongodb的開發筆記

時間過得很快,6月和7月忙的不可開交,糟心的事兒也是很多,杭州大連來回飛,也是呵呵。php

但願下個階段能沉浸下來,接着學本身想學的。記一下上幾周用了幾天時間寫的課設。由於課設的緣故,因此在短期裏瞭解下express+mongodb的組合,給APP端搭了個簡易的服務器,也開了後臺網站的web服務。簡單總結一下開發過程當中遇到的坑。html

 

1、關於express
瞭解node.js有半年多,第一次用node.js的框架來寫server,瞭解不是很深,簡單看了一下文檔以後就能夠上手了,開發入門難度低。
1.運行
express init以後覺得是node app.js命令運行項目,結果卻並非。app.js是項目入口文件不錯,可是自己也是一個module模塊,app.js的代碼裏面並無listenserver的操做,express的腳手架命令把項目啓動交給了bin/www文件,須要經過npm start啓動應用。
經過npm start的應用好像並不能實時重啓[?],因此能夠把www文件轉移至[new]start.js並運行node start.js,就可經過supervisor或者nodemon來自動監控&重啓應用了。java

 

2.中間件
express是基於中間件的。經過引入中間件執行處理函數,例如在處理一個get請求的時候會根據路由狀況在app.js裏順序執行函數,app.use('/admin', admin)就會處理全部localhost/admin下的請求,具體的第二級路由處理就交給了route/admin.js。這個課設裏我只本身定義了一箇中間件cookie-checker,用於登陸識別。在java或者php裏面能夠經過filter或者入口模塊檢測的方式來檢測cookie、判斷登陸,express裏面就剛簡化了,直接定義個cookie-checker中間件,放在了app.use('/api',api)和app.use('/admin', admin)中間,這樣全部的api請求(app端)無需cookie檢測,而admin下的請求所有須要通過登陸檢測操做,整個中間件的代碼以下:node

exports = module.exports = function(){
    return function(req,res,next){
        if( req.cookies.gid  == undefined || req.cookies.gid == null ){
            if( req.path != "/admin/login" ){
                res.redirect("/admin/login");
            }
            else{
                next();
            }
        }
        else{
            next();
        }
    }
}

 

3.模塊引用
express裏面對模塊互相引用目測並無作什麼處理,固然產生互相引用確定是我本身代碼的緣由。
互相引用具體的位置忘了是哪裏了,可是大概是articleModule.js和favoriteModule.js形成的,在處理mongodb的連表查詢時候的問題。mongodb的連表也是糟心,後來也沒作連表,直接把favorite操做的記錄都add進一張大表裏了。以前兩年一直用的是mysql或者是sqlserver,在實際應用裏nosql的精神仍是沒有領會,設計表的時候以爲還挺簡單,實際應用起來就發現跟mysql、sqlserver徹底不是一個路數,連表、主鍵、外鍵都沒有。mysql

 

4.mvc的模式
如今寫個server不基於mvc都很差意思說本身是寫server的。express裏面作的仍是不錯的,route、view、modules。
route下是路由文件,用於處理路由請求,而且根據請求調用對應module的函數。全部的請求都是經過req、res、next來操做,內部函數大可能是基於回調的。view下全部的模板文件,課設裏面使用的是jade,感受和smarty等模板語言沒什麼功能區別,映射、分佈視圖、公共模塊、模板繼承、if-else等邏輯判斷,該有的都有,jade的語法卻是變了,寫的不是html標籤,節點名稱、縮進控制層級。modules下自定義的原型模塊,例如課設裏面大概有這麼幾個module:ad、article、word、user等,模塊內部引入mongoose文件完成增刪改查操做,增刪改查數據庫的函數都是異步的,因此在文件下大部分函數也都是基於回調的。
例如API路由下的api/wordItem?id=5x23434fa5sk4dhid7a,獲取的是某條句子的信息。在api.js裏:web

/* 單句(id) api/wordItem?id=5x23434fa5sk4dhid7a */
router.get('/wordItem', function(req, res, next) {
    var _id = req.query.id;
    var _user = req.query.uid || -1;
    word.findById(_id,function(err,data){
        if( err ){
            data._id = -1;
        }
        favorite.check({t_id:data._id,user_id:_user},function(_f){
            data.flag = _f;
            res.send( data );
        });
    });
});

在word.js裏面:sql

//根據ID獲取word條目
var Word = mongodb.mongoose.model("word", wordSchema);
var wordModel = function(){};
//...
wordModel.prototype.findById = function(_id,callback){
    var id = _id || 1;
    Word.findOne({'_id':id}, function(err, obj){
        var  itemdata =  obj || {_id:-1} ;
        favorite.getCount({t_id:itemdata._id},function(err,count){
            itemdata.favorite = count ;
            callback(err,itemdata);
        });
    });
};

路由判斷---調用word原型的findById函數---函數內部執行mongoose封裝的WordModel的findOne操做,查詢結束後執行回調,將err參數和data參數做爲形參傳遞給回調函數。mongodb

5.文件上傳
用的是multer中間件,經過json配置直接處理了文件存儲位置、上傳回調。數據庫

app.use(multer({
    dest: 'public/upload/',
    limits: {
        fieldNameSize: 100,
        files: 2,
        fields: 5
    },
    onFileUploadComplete: function (file, req, res) {
        res.flag = true;
        res.fname = file.name;
    },
    onError: function (error, next) {
        res.flag = false;
        res.fname = "";
        next(error);
    }
}));

把public文件夾設置爲靜態路由:express

app.use(express.static(path.join(__dirname, 'public')));
相關文章
相關標籤/搜索