zoukankan      html  css  js  c++  java
  • [node.js]express+mongoose+mongodb的开发笔记

    时间过得很快,6月和7月忙的不可开交,糟心的事儿也是不少,杭州大连来回飞,也是呵呵。

    希望下个阶段能沉浸下来,接着学自己想学的。记一下上几周用了几天时间写的课设。因为课设的缘故,所以在短时间里了解下express+mongodb的组合,给APP端搭了个简易的服务器,也开了后台网站的web服务。简单总结一下开发过程中遇到的坑。

    一、关于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来自动监控&重启应用了。

    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下的请求全部需要经过登录检测操作,整个中间件的代码如下:

    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完全不是一个路数,连表、主键、外键都没有。

    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里:

    /* 单句(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里面:

    //根据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参数作为形参传递给回调函数。

    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文件夹设置为静态路由:

    app.use(express.static(path.join(__dirname, 'public')));
  • 相关阅读:
    读《阿里云是如何失控的》有感
    LeetCode Search in Rotated Sorted Array 在旋转了的数组中查找
    界面编程模仿篇(QQ登录界面逼真篇)
    最牛B的编码套路
    QinQ封装及终结详解
    seaJs学习笔记之javascript的依赖问题
    Deploy maven on Linux OS
    c++——inline内联函数
    c++——引用
    c++——const关键字
  • 原文地址:https://www.cnblogs.com/limingxi/p/4642304.html
Copyright © 2011-2022 走看看