Node pitfalls 2: lingering responses
One of the main appeals of Node is how it encourages asynchronous code. You may very well write synchronous code in Node, but if you do, you’re not going to reap the benefits, and you should probably use another platform. I’ll talk in another post about some of the challenges associated with JavaScript asynchronous code, but there is one specific consequence that made me trip more than a couple of times while I was learning Node: it is very easy to create wrong expectations about when or whether a specific callback will get called, and then things can go really bad.
Asynchronous code still requires a little more discipline than the synchronous equivalent: all the code involved needs to play nice and be considerate of what comes next, including in error cases. There is one thing in particular in a typical web request that needs to happen eventually: the response needs to end, and the connection with the server needs to be closed. On many web platforms, this will happen automatically once the end of the request lifecycle is reached.
On raw Node, you will need to do that explicitly, and you’ll need to make super-extra-sure that it will always happen no matter what. If you leave even one possibility that it doesn’t, then you’ll get a connection that remains open forever, or rather, until something times out. That’s bad, m’kay?
So what to do to ensure this never happens? Well, first, you need to have a response.end at the ends of all code paths in your application. Those code paths include error conditions, and time outs. Second, you need to remain very disciplined about calling back, and about error handling.