Async / await is one of the biggest revolutions (read: one of the sweetest syntactical sugars) that has come to JavaScript over the past few months, and has personally helped me appreciate the language a lot more.
At work, we rely quite a lot on ExpressJS to build small services deployed in our architecture and, as you can imagine, have converted a whole bunch of them to async / await over time.
One interesting problem, though, has been converting express routes to use async functions: my personal solution has been to write express-async-await, and I want to share the reasons and ideas behind the library in this post.
A typical express scenario
Before we understand the problem, I want to clarify the scenario we’re looking at — a simple app with a few routes and an error handler to catch’em all:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
As you see, we simply have a couple routes which use some promise-based service (we could even use callbacks, I’m using promises here just for the sake…) and an error handler that intercepts any error and returns a “standard” response should anything fail in the routes.
Can we do better?
The problem with async functions
Lauded for its simplicity and readability, async / await can help us make the code a bit more elegant:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Now, you probably see where I’m headed: each and every route we add needs to have some boilerplate to catch errors and forward them to the error handler, and that’s where my OCD kicked in — there needs to be a better way of doing this.
Solution 1: the wrapper
Turns out that the solution is quite simple, you can just create a wrapper that catches
the error and calls next
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Much better, right? Well, at least I think so: now our routes are one-liners that
defer to a service and error handling is out of the picture, as it’s taken care by
the asyncMiddleware
function (here’s a good article on the topic).
The biggest drawback, in my opinion, is that the routes are now looking less
“pure” than they should: they’re all wrapped in this asyncMiddleware
which looks
kind of awkward. What if we were able to “hide” this implementation detail from
our code?
Solution 2: express-async-await
That’s where express-async-await kicks in: it’s a tiny library I wrote to be able to monkey-patch your express app so that you don’t need to wrap each and every route:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
…and that’s it! The library takes care of monkey-patching express’ HTTP methods (like app.get
, app.post
, etc)
and automatically wrap them with the asyncMiddleware
we’ve seen earlier on.
Biggest drawback? Well, some are really against monkey-patching (for good reasons) but, when used with caution, I think it can be a really effective way to enhance a library that’s missing an interesting feature1.
- By the way, my bet is that within a year express is going to support this “natively” ↩