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?
Can we export async function? This is not possible. Since the value is retrieved asynchronously, all modules that consume the value must wait for the asynchronous action to complete first – this will require exporting a Promise that resolves to the value you want.
NodeJS is an asynchronous event-driven JavaScript runtime environment designed to build scalable network applications. Asynchronous here refers to all those functions in JavaScript that are processed in the background without blocking any other request.
Module exports are the instructions that tell Node. js which bits of code (functions, objects, strings, etc.) to export from a given file so that other files are allowed to access the exported code.
Asynchronous By Default. To provide concurrency, time-consuming operations (in particular I/O events and I/O callbacks) in Node. js are asynchronous by default.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With