Is it ok to initialize exports asynchronously in a node.js module?


Question

As MongoDB database access and initialization is asynchronous on Node.js, I would like to define one module per collection that exports wrapped db calls after db initialization.

Such a "Cars.model.js" module looks like that:

var db = require("mongodb");
db.collection("cars", function(err, col) {
    exports.getCars = function(callback) {
        col.find({}, callback);
    };
});

so that other modules can run:

var carModel = require("Cars.model.js").getCars;
getCars(err, cars) {
    // (do something with cars here...)
};

It happened to me that getCars was undefined, because db access was not yet initialized at the time my second module was run.

How do you deal with creating such asynchronous db models?

1
9
6/21/2011 12:34:09 PM

You cannot write to exports after you've left the file. You must be blocking. To avoid being blocking I would use lazy loading of resources.

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");
});

Use event emitters to emulate lazy loading. You may want to generalize to a LazyLoadedCollection class/object to make the code neater / more DRY.

11
6/21/2011 2:05:41 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon