可以在node.js模块中异步初始化导出吗?

时间:2011-06-21 12:34:09

标签: model-view-controller design-patterns mongodb asynchronous node.js

由于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未定义,因为我的第二个模块运行时数据库访问尚未初始化。

您如何处理创建此类异步数据库模型?

3 个答案:

答案 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);
};

此解决方案将异步问题从模型转移到根数据库模型,使模型更易于开发。