I'm building an API with Koa. I have all my routes in place with koa-router. Each route uses a controller that has all the logic for a given mongoose model. I've read the Koa docs on error-handling and understand the use of await
ing in a try/catch
block. There they mention a Default Error Handler should be set at the beginning of the middleware chain. So if I was to have something like the following, I should have resonable error handling for the route at router.get()
:
const Koa = require('koa');
const Router = require('koa-router');
const app = new Koa();
const router = new Router();
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
err.status = err.statusCode || err.status || 500;
throw err;
}
});
router
.get('/', async (ctx, next) => {
console.log('Got Route');
//ctx.body = users;
});
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000, () => console.log('Koa app listening on 3000'));
If I was to have something slightly more complex at this route, is there any benefit of adding another try/catch
inside the route?
router
.put('/', async function updateOnServer(ctx, next) {
try {
await Model.updateOne({
_id: ctx.params.id,
}, {
field1: ctx.request.body.field1,
$push: { field2: ctx.request.body.field2 },
}).exec();
} catch (e) {
console.log(e);
}
await next();
});
Am I just adding redundant error handling here?
I re-read the docs on Error Handling and also found this little tip on the Koa Wiki. From that, I've concluded the following:
However, the default error handler is good enough for most use cases.
The default error handler in this case is the Koa-built-in error handler. You do not need to include any kind of custom error handling in the code you write. Koa will write out a stack trace along with the error message, etc.
If you want to modify how the error is handled, add something like the suggested middleware at the very beginning of the middleware chain:
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
err.status = err.statusCode || err.status || 500;
ctx.body = err.message;
ctx.app.emit('error', err, ctx);
}
});
If you want to change that again for a specific route, or a special bit of logic, then add another try/catch
block at that point (as per my above):
router
.put('/', async function updateOnServer(ctx, next) {
try {
await Model.updateOne({
_id: ctx.params.id,
}, {
field1: ctx.request.body.field1,
$push: { field2: ctx.request.body.field2 },
}).exec();
} catch (e) {
ctx.status = 418;
ctx.body = "a custom error message, with nothing really helpful";
}
await next();
});