2014-10-09 48 views
1

我使用Node anb Mongodb Native构建应用程序。我正在开发一个db模块,我可以在其他模块中调用它,以便最终只使用一个连接。该模块db.js开始了这段代码:使用异步队列来控制数据库连接请求

var _db = null; 
var getDb = module.exports.getDb = function(callback) { 
    if (_db) { 
    console.log('_db returned'); 
    return callback(null, _db); 
    } 
    MongoClient.connect('mongodb://localhost:' + config.db.port + '/' + config.db.name, {native_parser: true}, function (err, db) { 
    if (err) return callback(err); 
    console.log('_db created'); 

    _db = db; 
    callback(err, _db); 
    }); 
}; 

在我需要一个数据库连接其它模块我这样做

db.getDb(function (err, connection) { 
    // Do something with connection 
}); 

它工作正常。但一个令人不快的问题是,如果我的代码在很短的时间内多次调用getDb,我最终会得到几个连接副本。就像如果我做我的db.js要求,并需要一个数据库连接

我现在想通过排队他们控制到getDb呼叫所有模块的最开始getDb呼叫,这样,只有绝对的第一通话将创建一个连接并保存在_db。所有以后的呼叫都将获得创建的连接_db作为回报。我相信Async queue将帮助我与此...

问题是,我不明白我如何写这与异步队列。该文档有点含糊,我没有在网上找到更好的例子。也许你可以给我一些提示。这是我走到这一步......

var dbCalls = async.queue(function (task, callback) { 
    if (_db) { 
    console.log('_db returned'); 
    return callback(null, _db); 
    } 
    MongoClient.connect('mongodb://localhost:' + config.db.port + '/' + config.db.name, {native_parser: true}, function (err, db) { 
    if (err) return callback(err); 
    console.log('Connected to mongodb://localhost:' + config.db.port + '/' + config.db.name); 

    _db = db; 
    callback(null, _db); 
    }); 
}, 1); 

// I guess this .push() must be the exposed (exported) API for other modules to get a connection, but how do I return it to them, 
dbCalls.push(null, function (err) { 
    console.log('finished processing foo'); 
}); 

dbCalls.push(null, function (err) { 
    console.log('finished processing bar'); 
}); 

我不明白作为第一个参数传递给.push()对象我应该使用什么如果?现在它的null如何将连接和可能的错误传递给发出调用的模块?

回答

2

一个快速和肮脏的解决方案,而async.queue

var _db  = null; 
var _err  = null; 
var _queue = []; 
var _pending = false; 

var getDb = module.exports.getDb = function(callback) { 
    if (_err || _db) { 
    console.log('_db returned'); 
    return callback(_err, _db); 
    } else if (_pending) { // already a connect() request pending 
    _queue.push(callback); 
    } else { 
    _pending = true; 
    _queue.push(callback); 
    MongoClient.connect(..., function (err, db) { 
     _err = err; 
     _db = db; 
     _queue.forEach(function(queuedCallback) { 
     queuedCallback(err, db); 
     }); 
    }); 
}; 
+0

谢谢!我非常欣赏这种非依赖解决方案,因为它让我深入了解像异步(可能)这样的库如何在幕后工作!从长远来看,我认为知道如何解决普通的js问题将为您提供最好的服务! – 2014-10-09 10:34:25