Patterns and abstraction
Error handling in node.js
As an awesomely consistent and well implemented set of APIs, all API calls in
node.js that perform any kind of IO take a function callback to run on IO
completion. This is a very fundamental practice at the core of the node.js
asynchronous evented model. A familiar site to anyone familiar with node is the
pattern of arguments that are passed to the callback. Typically, asynchronous
callbacks will take one or two arguments,
(error, value) . The
most important part for this article being that error is always the first
argument passed to the callback.
The error passed as the first argument to any aysnchronous callback is representative of any errors that might have occurred during the asynchronous operation. Error will be false if no error was raised and non false otherwise. In node.js you often have nested aysnchronous requests and a common approach to error handling is to pass the errors back up the event chain to be handled by a layer knowing what to do with it. This is demonstrated in the bellow pseudo code js example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
There it is the error passing pattern. If you write node.js code you can probably find this pattern throughout your code base. If you can’t it means you’re probably not handling errors which is a big no go.
The pattern can be written a couple different ways
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
So the money making question is how do we factor out this repetitive pattern being the ace functional programmers that we like to think that we are?
Heres the solution i came up with, i call it the pass pattern. I call it the pass pattern, but really it’s more of an abstraction.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
So this requires you to setup a function called pass which acts as a closure generator for augmenting the asynchronous callback. The error checking gets dropped from the asynchronous callback, yet the error checking still takes place. The asynchronous callback itself is only ran when no error is present and as a byproduct, we can safely drop the error argument from the first argument of the callback. Just as important, the next callback is automatically forwarded or “passed” the error if one is present.
The above example of pass is just introductory code. The full version of the pass abstraction i use in my code is as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
This version allows me to override error messages so if i get back a DB failure
error from the database while calling it from the registration form i can
override the message with something more meaningful to the user that will get
passed along instead. My version also allows context binding so i can avoid
var self = this; annoyances.