• node.js对mongodb的连接&增删改查(附async同步流程控制)


    1.启动mongodb数据库

    官网下载mongodb数据库

    在mongodb根目录下创建文件夹:假设取名为test。 
    我们认为test就是mongodb新建的数据库一枚。

    创建批处理文件 xxx.bat,内容如下:

    运行e盘mongodb文件夹下bin目录下的 mongod.exe,参数为 
    -dbpath E:mongodb est。

    E:mongodbinmongod.exe -dbpath E:mongodb	est

    这样就启动了mongodb下test数据库的服务器。

    2.加载mongodb模块

    在我们的node.js项目中直接npm入mongodb模块

    npm install mongodb --save

    3.依赖mongodb模块

    在想要写对mongodb的增删改查逻辑的js文件下加入以下依赖

    var mongo = require("mongodb");

    4.通用小函数

    写了几个通用的小函数,最后创建一个对象,将函数全都挂到对象上,最后把对象exports出去即可。

    /**
     * 创建数据库服务器并开发名为databaseName的数据库
     * @param host ip
     * @param port 端口
     * @param databaseName
     * @return  打开失败返回-1 ,成功返回database
     */
    function openDatabase(host,port,databaseName){
        //创建数据库所在的服务器
        var server = new mongo.Server(host, port, {auto_reconnect: true});
        var db = new mongo.Db(databaseName, server, {safe: true});
        db.open(function (err, db) {
            if (err) {
                console.log('打开数据库失败');
                return -1;
            }
            else {
                console.log('打开数据库成功');
    
            }
    
        });
        return db;
    }
    /**
     * 连接数据集合
     * @param db 数据库
     * @param collectionName 数据集合名称
     * @return 成功返回collection,失败返回-1
     */
    function openCollection(db,collectionName){
        db.collection(collectionName,{safe:true},function(errcollection,collection){
            if(!errcollection){
                console.log('连接数据集合成功');
                return collection;
    
            }else{
                console.log('连接数集合失败');
                return -1;
            }
        });
    
    
    }
    /**
     * 插入数据
     * @param collection
     * @param tmp 要插入的数据
     * @return 成功返回collection,失败返回-1
     */
    function insertCollection(collection,tmp){
        //var tmp = {username:'hello',password:1};
        collection.insert(tmp,{safe:true},function(err, result){
            if(err){
                console.log('传入数据集合失败'+tmp);
                return -1;
            }else {
                console.log('插入数据集合成功'+result);
    
            }
        });
        return collection;
    }
    /**
     * 查询数据集合 没有条件
     * @param collection
     * @return 成功返回查询到的数据集合内容,失败返回-1
     */
    function findCollectionNoCondition(collection){
        collection.find().toArray(function(errfind,cols){
            if(!errfind){
                console.log('查询数据集合成功'+JSON.stringify(cols));
                return JSON.stringify(cols);
            }else {
                console.log('查询数据集合失败');
                return -1;
            }
        });
    }
    /**
     * 查询数据集合 有条件
     * @param collection
     * @return 成功返回查询到的数据集合内容,失败返回-1
     */
    function findCollectionHasCondition(collection,tmp){
        collection.find(tmp).toArray(function(errfind,cols){
            if(!errfind){
                console.log('查询数据集合成功'+JSON.stringify(cols));
                return JSON.stringify(cols);
            }else {
                console.log('查询数据集合失败');
                return -1;
            }
        });
    }
    /**
     * 删除数据集合
     * @param collection
     * @param tmp
     * @return 成功返回数据集合,失败返回-1
     */
    function removeCollection(collection,tmp){
        //var tmp = {username:'hello',password:1};
        collection.remove(tmp,{safe:true},function(err, count){
            if(err){
                console.log('删除数据集合失败'+tmp);
                return -1;
            }else {
                console.log('删除数据集合成功'+count);
                return collection;
            }
        });
    }


    5.async模块解决node.js异步架构下同步逻辑的实现

    看到《超实用的node.js代码段》这本书上,讲到Node.js是异步I/O驱动,所以在我们顺序运行上面的几个函数的时候,一定会遇到一个问题:如果前面de函数耗时长,那么后面的函数不会等前面的函数运行完,而是直接运行。但是我的前一个函数的运行结果是要被后一个函数使用的呀。

    这时候就需要在异步I/O下进行串行控制流控制。

    书中介绍了async模块,手续爱你第三方引入。

    npm install async --save
    • 1

    require进来

    var async=require("async");
    • 1

    使用方法: 
    Nodejs异步流程控制Async

    我这里使用的是waterfall瀑布模式流程控制 
    github waterfall机制使用demo

    然后我就天真的使用了

     //使用async瀑布模型流程控制执行 数据库的连接查询
        async.waterfall([
            function(callback){
                var db;
                db=user.openDatabase("localhost",27017,"test");
                callback(null,db);
            },
            function(db,callback){
                var collection;
                if(db!=-1){
                    collection=user.openCollection(db,'users');
                }
                callback(null,collection);
            },
            function(collection,callback){
                var res;
                if(collection!=-1){
                    res=user.findCollectionNoCondition(collection);
                    console.log(res);
                    callback(null,3);
                }
            }
        ],function(err,result){
            console.log("async瀑布模型流程控制执行成功"+result);
        })
    结果还是第二个函数先于第一个函数运行成功,导致第三个函数不能正确运行。

    **********************************************************************
    一、使用模块Q的promise机制实现数据库操作的同步问题

    1.install

    npm install q --save

    2.require

    var Q=require('q');

    3.重写数据库CRUD操作方法

    /**
     * 创建数据库服务器并开发名为databaseName的数据库
     * @param host ip
     * @param port 端口
     * @param databaseName
     * @return  打开失败返回-1 ,成功返回database
     */
    function openDatabase(host,port,databaseName,collectionName){
        //创建数据库所在的服务器
    
        var deferred = Q.defer();
        var server = new mongo.Server(host, port, {auto_reconnect: true});
        var db = new mongo.Db(databaseName, server, {safe: true});
        db.open(function (err, db) {
            if (err) {
                console.log('打开数据库失败');
                deferred.reject(err);
            }
            else {
                console.log('打开数据库成功');
                deferred.resolve([db,collectionName]);
    
            }
    
        });
        return deferred.promise;
    }
    /**
     * 连接数据集合
     * @param db 数据库
     * @param collectionName 数据集合名称
     * @return 成功返回collection,失败返回-1
     */
    function openCollection(db,collectionName){
        var deferred = Q.defer();
        db.collection(collectionName,{safe:true},function(errcollection,collection){
            if(!errcollection){
                console.log('连接数据集合成功');
                deferred.resolve(collection);
    
            }else{
    
                console.log('连接数集合失败');
                deferred.reject(errcollection);
            }
        });
        return deferred.promise;
    
    }
    /**
     * 插入数据
     * @param collection
     * @param tmp 要插入的数据
     * @return 成功返回collection,失败返回-1
     */
    function insertCollection(collection,tmp){
        //var tmp = {username:'hello',password:1};
        collection.insert(tmp,{safe:true},function(err, result){
            if(err){
                console.log('传入数据集合失败'+tmp);
                return -1;
            }else {
                console.log('插入数据集合成功'+result);
    
            }
        });
        return collection;
    }
    /**
     * 查询数据集合 没有条件
     * @param collection
     * @return 成功返回查询到的数据集合内容,失败返回-1
     */
    function findCollectionNoCondition(collection){
        var deferred = Q.defer();
        collection.find().toArray(function(errfind,cols){
            if(!errfind){
                console.log('查询数据集合成功'+JSON.stringify(cols));
                deferred.resolve(JSON.stringify(cols));
            }else {
                console.log('查询数据集合失败');
                deferred.reject(errfind);
            }
        });
    
        return deferred.promise;
    }
    /**
     * 查询数据集合 有条件
     * @param collection
     * @return 成功返回查询到的数据集合内容,失败返回-1
     */
    function findCollectionHasCondition(collection,tmp){
        collection.find(tmp).toArray(function(errfind,cols){
            if(!errfind){
                console.log('查询数据集合成功'+JSON.stringify(cols));
                return JSON.stringify(cols);
            }else {
                console.log('查询数据集合失败');
                return -1;
            }
        });
    }
    /**
     * 删除数据集合
     * @param collection
     * @param tmp
     * @return 成功返回数据集合,失败返回-1
     */
    function removeCollection(collection,tmp){
        //var tmp = {username:'hello',password:1};
        collection.remove(tmp,{safe:true},function(err, count){
            if(err){
                console.log('删除数据集合失败'+tmp);
                return -1;
            }else {
                console.log('删除数据集合成功'+count);
                return collection;
            }
        });
    }

    里面的关键点是:

    • 定义defered对象var deferred = Q.defer();
    • 定义函数成功执行的resolve对象deferred.resolve(JSON.stringify(cols));
    • 定义函数成功失败的error对象 deferred.reject(errfind);
    • 最后返回一个新的promise对象,用来return deferred.promise;

    4.链式调用

      user.openDatabase("localhost",27017,"test","users")
            .then(function(data){
                return user.openCollection(data[0],data[1])
            })
            .then(user.findCollectionNoCondition)
            .done(function(data){
                console.log('promise执行成功');
            },function(err){
               console.log("promise执行失败:"+err);
            });

    5.log打印结果

    GET / 304 55.922 ms - -
    打开数据库成功
    连接数据集合成功
    GET /stylesheets/style.css 304 6.048 ms - -
    查询数据集合成功[{"_id":"57731d3a239f75379769ce31","username":"liuchen","password":"12345"},{"_id":"577328ab5c8d6cf43b3e214d","username":"hello","password":1},{"_id":"577331f35c8d6cf43b3e214e","username":"hello","password":1},{"_id":"57733bf400a7090c35122844","username":"hello","password":1},{"_id":"57733c0300a7090c35122845","username":"hello","password":1},{"_id":"57733c0af8d7813443d51c27","username":"hello","password":1}]
    promise执行成功
















  • 相关阅读:
    定制事件 观察者模式
    定时器的高级运用 优化
    tamper-proof 对象 nonextensible对象 sealed对象 frozen对象
    函数柯理化
    跨域 Ajax 其他可选技术 异步
    Ajax 跨域 异步 CORS
    原样输出html标签
    JavaScript
    css 中name的用途
    iview 按需引入解决加载慢的问题
  • 原文地址:https://www.cnblogs.com/pyj63/p/8080476.html
Copyright © 2020-2023  润新知