我正在尝试创建一个mongoClient连接池模块以在我的项目中使用。问题是我第一次加载页面并调用mongoFactory时,似乎我的mongoConnection尚未建立。之后每隔一段时间我加载页面就可以了。不知道我在这里缺少什么..
这是我的mongoFactory.js
/**
* Creates and manages the Mongo connection pool
*
* @type {exports}
*/
var constants = require('../js/constants.js');
var Q = require('q');
var MongoClient = require('mongodb').MongoClient;
var db = null;
var getDb = function() {
console.log('db = '+db);
// If the connection pool has not been created or has been closed, create it, else return an existing connection
if (db === null) {
var def = Q.defer();
// Initialize connection once
MongoClient.connect(constants.mongoUrl, function (err, database) {
if (err) {
def.reject(err);
throw err;
}
console.log('inside connection');
db = database;
def.resolve();
});
def.promise.then(function () {
console.log('before returning connection');
return db;
});
} else {
console.log('connection already exists. returning');
return db;
}
}
module.exports.getDb = getDb;
这是我的文件,我正在调用mongoFactory
var mongoFactory = require('../../lib/mongoFactory');
module.exports = function() {
return {
find: function find(callback) {
var db = mongoFactory.getDb();
var cases = db.collection('mycollection'); // <-- First time i load the page, errors b/c db is undefined. Every other time after that it works just fine. ERROR: TypeError: Uncaught error: Cannot call method 'collection' of undefined
...
答案 0 :(得分:2)
您的mongoFactory.getDb
应该返回一个承诺,该承诺将在建立连接后完成(第一次将需要一段时间,之后将立即发生)。
/**
* Creates and manages the Mongo connection pool
*
* @type {exports}
*/
var constants = require('../js/constants.js');
var Q = require('q');
var MongoClient = require('mongodb').MongoClient;
var db = null;
var getDb = function() {
var def = Q.defer();
console.log('db = '+db);
// If the connection pool has not been created or has been closed, create it, else return an existing connection
if (db === null) {
// Initialize connection once
MongoClient.connect(constants.mongoUrl, function (err, database) {
if (err) {
def.reject(err);
}
console.log('inside connection');
db = database;
def.resolve(db);
});
} else {
def.resolve(db);
}
return def.promise;
}
module.exports.getDb = getDb;
并使用:
var mongoFactory = require( './mongoFactory' );
var con = mongoFactory.getDb();
con.done( function(db) {
// use db here
} );
con.fail( function(err) {
// error occurred
} );
您可能需要签出mongoskin这是一个围绕node-mongodb-native的承诺包装。
答案 1 :(得分:1)
在函数内部构造延迟不会自动阻止它 - 实际上它不能,promises are still asynchronous。
在undefined
的情况下,您的函数确实没有返回任何内容(即db === null
),并且只有在先前调用已经建立的情况下才返回数据库连接。相反,它应始终返回 Promise ,代表(可能是以后到达的)最终连接。
/**
* Creates and manages the Mongo connection pool
*
* @type {exports}
*/
var constants = require('../js/constants.js');
var Q = require('q');
var MongoClient = require('mongodb').MongoClient;
var dbPromise = null;
module.exports.getDb = function getDb() {
// If the connection pool has been created or is being created, return the existing promise for that, else create it and return the promise for that
if (dbPromise === null) {
var def = Q.defer();
// Initialize connection once
MongoClient.connect(constants.mongoUrl, function (err, database) {
if (err)
def.reject(err);
else
def.resolve(database); // let the database be the result value of the promise!
});
return dbPromise = def.promise;
} else {
return dbPromise;
}
};
既然你的函数返回了一个promise,你需要在then
回调中使用它:
find: function find(callback) {
return mongoFactory.getDb().then(function(db) {
// db is always available in the promise callback
var cases = db.collection('mycollection');
// return a promise or a value from the callback
}); // and find will return a promise for that value
}
答案 2 :(得分:0)
MongoClient.connect
本质上是异步的,为什么不以nodejs的方式呢?我会更改您的getDb
签名以接受回调:
var getDb = function(callback) {
console.log('db = '+db);
// If the connection pool has not been created or has been closed, create it, else return an existing connection
if (db === null) {
// Initialize connection once
MongoClient.connect(constants.mongoUrl, function (err, database) {
if (err) {
callback(err);
return;
}
console.log('inside connection');
db = database;
callback(null, db);
});
} else {
console.log('connection already exists. returning');
callback(null, db);
}
}
然后你的消费者必须:
mongoFactory.getDb(function(err, db) {
if (err) {
// handle error
}
var cases = db.collection('mycollection');
});