Defining object request handlers in express: obj.bind(obj) to the rescue

If you’re coming from a class-oriented environment of web development you might be used to handler classes that are bound to a dispatching frontdoor and that handle requests. For example I’m used to write something like this in SpringMVC:

@Controller
public class SomeHandler {

	@RequestMethod("/testobj")
	public void handle(HttpServletRequest req, HttpServletResponse resp) {
		resp.println("Hi there");
	}
}

When moving to a Javascript / event oriented backend environment things are a little different. The highly acclaimed and well designed expressjs framework for node.js, that’s based on the middleware-oriented connect framework uses callback functions that are bound to a common routing handler. If you’ve written backend code for expressjs you most likely have been stumbling upon constructs like this:

app.get('/testobj', function(req, res) {
	res.end("Hi there");
});

Instead of encapsulating response behaviour in its own class you are defining anonymous functions and hand them over as handler middleware. No doubt: if you’re going to write your code like this you’ll end up with a giant main script and lots of those anonymous functions.

The idea of encapsulation is also known to Javascript, though, so I started to combine handler functions into handler objects living inside their own modules. Here’s an example:

// modules/testobj.js
function TestObj(name) {
	this.name = name;
}
TestObj.prototype.sayName = function() {
	return this.name;
};
/**
 * handler for /testobj
 */
TestObj.prototype.render = function(req, res) {
	var aName = this.sayName();
	console.log("aName: " + aName);
	res.end(aName);
};
exports.TestObj = TestObj;

The object TestObj is exposed while the methods are added to its prototype. The handler object gets some environment – instead of handing over a simple name in the constructor imagine to hand over a database connection or a facebook client object; you name it. Since the middleware interface of the connect framework only accepts functions with a (req, res) signature (I simplify a little here) you cannot handover your “dependency injected” object but rather have to handover its member / prototype functions. So you are tempted to write something like this:

var to = require('./modules/testobj');
var anObject = new to.TestObj("Stefan");
app.get('/testobj', anObject.render);

A request to /testobj will be sent to the anObject.render middleware that’s supposed to render “Stefan” to the screen (as TestObj is constructed with that name). Instead it shows nothing. If you have a look at your console output you’ll notice that “aName” is undefined.

Without going into too much detail the easy explanation for this behaviour is that by referencing the function it’s loosing its reference to “this” because it’s addressed directly. If you want you can log “this” to the console inside the handler function – it’s going to show the global object (node) since all variables (functions are also variables in JavaScript) are bound to it if there is no other context provided.

The solution is to bind the this context to the function so it’s kept even if called by someone else (namely the connect dispatcher). Luckily this feature has been implemented into ECMAScript5 which node.js is based on so the solution is really easy once you’ve found it:

app.get('/testobj', anObject.render.bind(anObject));

will “rebind” the object reference as this to the .render function and the code works as expected.

Took quite a while to figure that one out. Hope to be helpful!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s