Introduction
In June 2017, has been released the 8th version of ECMAScript (ES8), as usual, a lot of interesting new features has been published.
As a reminder, ECMAScript is a standardization of script-like languages like Javascript. Throughout the different versions, ECMAScript brings standardization of functions, new functionalities and deprecates certain other functions.
One of the most important features of ES8 is the arrival of the async / await keywords.
The target of this article isn’t to show you how to use async / await, but how to use them with the Express framework.
Why?
If you are an async/await functions addict, it’s most certainly because you like writting clean code ? ?
So, I deduce you dislike to be forced by a framework to write crappy code like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
makeTheWorldBetter() .then(() => { // ... }) .then(() => { // ... }) .then(() => { // ... }) .then(() => { // ... }) .then(() => { // ... }) .then(() => { // ... }) .catch((e) => { // ... }) |
What’s the Express problem with async/await?
To be precise, it’s not really « an express problem », this is the normal express operating mode.
With Express, when you want to create a controller or a middleware function which uses a promise you must use .then sentences like:
1 2 3 4 5 6 7 8 9 10 11 12 |
import express from 'express'; const app = express(); app.get('/example', function (req, res, next) { myPromise .then((result) => { res.status(200).send({success: true}); }) .catch((error) => { res.status(500).send({success: false}); }); }); |
The problem is simple, Express does not allow to pass a Promise as second argument, it must be function or Router instance.
Example of not working code. ⚠
1 2 3 4 5 6 7 8 9 10 |
import express from 'express'; const app = express(); app.get('/example', async function (req, res, next) { await myPromise .catch((error) => { res.status(500).send({success: false}); }); res.status(200).send({success: true}); }); |
Okay, but what’s the correct way?
The trick is very simple but very useful, for using async/await function into your express middlewares, you just need to wrap your functions with a Promise:
1 2 3 4 5 6 7 |
const wrapAsync = (fn) => { return (req, res, next) => { const fnReturn = fn(req, res, next); return Promise.resolve(fnReturn).catch(next); } }; |
For helping the community, I’ve created an open source package to simplify the wrapper usage: @rimiti/express-async.
The package has been developed with TypeScript and the code is 100% covered by tests.
Example with @rimiti/express-async package.
1 2 3 4 5 6 7 |
import express from 'express'; import {wrapAsync} from '@rimiti/express-async'; const app = express(); app.get('/example', wrapAsync(async function example(req, res, next) { res.status(200).send({success: true}); })); |
Simple, clean and powerful.. ?
Sources
- Github page: @rimiti/express-async
2 comments
Hadrien
Posted on 12 février 2019 at 14 h 33 minThank you for sharing this post.
Dimitri DO BAIRRO
Posted on 12 février 2019 at 14 h 43 minThanks for your spelling fixes.