由于MongoDB数据库访问和初始化在Node.js上是异步的,我想在db初始化后为每个集合定义一个导出包装db调用的模块。
这样的“Cars.model.js”模块看起来像这样:
var db = require("mongodb");
db.collection("cars", function(err, col) {
exports.getCars = function(callback) {
col.find({}, callback);
};
});
以便其他模块可以运行:
var carModel = require("Cars.model.js").getCars;
getCars(err, cars) {
// (do something with cars here...)
};
我发现getCars
未定义,因为我的第二个模块运行时数据库访问尚未初始化。
您如何处理创建此类异步数据库模型?
答案 0 :(得分:11)
离开文件后,您无法写入exports
。你必须阻止。为了避免阻塞,我会使用延迟加载资源。
var carCol;
var carEmitter = new require("events").EventEmitter;
exports.getCars = function(callback) {
// if no car collection then bind to event
if (carCol === undefined) {
carEmitter.on("cars-ready", function() {
callback(carCol);
});
} else {
// we have cars, send them back
callback(carCol);
}
}
db.collection("cars", function(err, col) {
// store cars
carCol = col;
// tell waiters that we have cars.
carEmitter.emit("cars-ready");
});
使用事件发射器模拟延迟加载。您可能希望概括为LazyLoadedCollection
类/对象,以使代码更整洁/更干燥。
答案 1 :(得分:2)
我是个新人,所以不要生我的气......
我正在使用承诺:
var db = require("mongodb"),
Q = require('q'),
getCarsDefer = Q.defer();
exports.getCars = getCarsDefer.promise;
db.collection("cars", function(err, col) {
if(err){
getCarsDefer.reject(err);
}else{
getCarsDefer.resolve(Q.ninvoke(col,'find'));
};
});
所以你可以这样开车:
var carModel = require("Cars.model.js").getCars;
getCars.then(cars) {
// (do something with cars here...)
};
这是一个坏主意,请让我知道,因为这就是我现在正在做的事情。
答案 2 :(得分:0)
我相信这个简单的解决方案是有效的:通过对可以调用模型之前填充的集合缓存的同步调用替换对getCars()
的异步调用。
main.js应用程序启动器模块:
var db = require("mongodb");
exports.collectionCache = {};
db.collection("cars", function(err, col) {
exports.collectionCache["cars"] = col;
// ready => start application logic (incl. models) here
});
因此“Cars.model.js”看起来像那样:
var col = require("main").collectionCache; // populated
exports.getCars = function(callback) {
col["cars"].find({}, callback);
};
此解决方案将异步问题从模型转移到根数据库模型,使模型更易于开发。