Skip to content

Instantly share code, notes, and snippets.

@scwood
Last active January 13, 2018 00:31
Show Gist options
  • Select an option

  • Save scwood/13ce8ba54b5a5851aa69b3d4e2ed2959 to your computer and use it in GitHub Desktop.

Select an option

Save scwood/13ce8ba54b5a5851aa69b3d4e2ed2959 to your computer and use it in GitHub Desktop.
async functions, next(error) and why it's neccessary
// Some background:
// Express will handle uncaught exceptions inside of middleware by sending them
// to the default error handler.
app.get('/some/endpoint', (req, res, next) => {
const a = {};
a.some.fake.prop;
// TypeError: Cannot read property 'prop' of undefined
});
// When someone hits /some/endpoint, express will send the request to the
// default error handler which sends a 500 and a generic error message.
// This is great, however this falls apart as soon as you introduce
// asynchronous behaviour. Fortunately, we can send errors to the error handler
// manually by calling next(error);
// Let's imagine we try to connect to a database in the endpoint but the server
// doesn't have a connection
app.get('/some/endpoint', (req, res, next) => {
doSomeDatabaseThing((error, result) => {
// Error: can't connect to database!
res.send('success');
});
});
// Express knows nothing about this connection error because it happened in an
// asynchronous context. We have to explicitly check if error exists and if it
// does, we need to send it to the error handler manually
app.get('/some/endpoint', (req, res, next) => {
doSomeDatabaseThing((error, result) => {
if (error) {
next(error);
return;
}
res.send('success');
});
});
// Above is how you would pass errors down while using an error first callback
// style asynchronous function but these principles still apply to promises
app.get('/some/endpoint', (req, res, next) => {
doSomeDatabaseThing()
.then((result) => res.send('success'))
.catch(next); // on caught error, we will call next
// the above is identical to saying .catch((error) => next(error))
});
// If an error happens in a promise the only way to send it down to the error
// handler is catch in the .catch block and send it on.
// Likewise with async functions, you need a top level try catch that
// encompasses the whole function. If an error is thrown outside that try-catch
// it will be lost because asynchronous functions return a promise implicitly,
// so it's important that the try-catch wraps the entire function.
app.get('/some/endpoint', async (req, res, next) => {
try {
const result = await doSomeDatabaseThing();
res.send('success');
} catch (error) {
next(error);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment