In our applications, we have a data adapter module whose sole purpose is to access data in some way. These adapters are event emitters, which emit an event when a query has completed, and sends back the data in common err, data
format that callbacks expect.
Let's get to some code to provide some information about the issue I'm trying to solve.
var
_ = require("underscore"),
Rosters = require("../adapters").mlb.Rosters,
dbConfig = require("../config/db"),
rosters = Rosters( dbConfig );
exports.team = function( req, res, next ) {
var bindHelperEvents = _.once(function() {
rosters.on("team", function(err, roster) {
if (!err) {
res.send( roster );
return;
}
next(err);
});
});
bindHelperEvents();
rosterHelper.team( req.params );
};
You can see in the code above we're binding an event handler only once (to avoid stacking event handlers), but it happens when someone makes a request. This - in my opinion - is not a very good way of doing this.
Here's an alternate way of doing this.
var
Rosters = require("../adapters").mlb.Rosters,
dbConfig = require("../config/db"),
rosters = Rosters( dbConfig );
rosters.on("team", function(err, data, req, res, next) {
if (!err) {
res.send( roster );
return;
}
next(err);
});
// Explicitly written for clarity
exports.team = function(req, res, next) {
rosters.team(req, res, next);
}
You can see now, that the event handler is bound when the server starts, rather than during the request response cycle, which is what I'm looking for.
The debate I'm having deals with passing req, res, next
into the adapter's function call. Ideally we'd like the adapter's interface to accept either an object of parameters, or a list of parameters rosters.teams(req.params) || rosters.teams(req.params.id, req.params.limit)
.
Is there a way to bind the event handler outside the req/res cycle and still have access to res, next in the scope of the callback, without changing the adapter's function call?
e.g.
var
Rosters = require("../adapters").mlb.Rosters,
dbConfig = require("../config/db"),
rosters = Rosters( dbConfig );
// How do I call res.send or next?
rosters.on("team", function(err, data) {
if (!err) {
res.send( roster );
return;
}
next(err);
});
// Explicitly written for clarity
exports.team = function(req, res, next) {
rosters.team(req.params);
}
EDIT (Added current code for Rosters):
var
HelperBase = require("../HelperBase"),
util = require("util");
util.inherits( Helper, HelperBase );
module.exports = Helper;
function Helper( options ) {
if ( !( this instanceof Helper ) ) {
return new Helper( options );
}
HelperBase.call( this, options );
};
Helper.prototype.team = function( params ) {
var
criteria = {
id: params.id,
...
};
this.db.collection("rosters").find( {unixstamp:-1} ).sort( sortCrit ).limit(1).toArray(function( err, rosters ) {
this.emit( "team", err, rosters[0] || {} );
return;
}.bind( this ) );
};