앞에서 언급되었던 사용자에 의한, 서버에 의한 에러들을 핸들링할 때, 비동기적인 에러에 대해 Promise().catch(next) 또는 async function을 사용하면서 try-catch문을 이용하여 에러 핸들링을 해왔다.
특히 async의 비동기 처리를 좀더 선호하는 편이지만 매번 try-catch문을 작성하는 것은 귀찮고 실수하기 쉽다.
그래서 async request handler함수를 작성하여 재활용한다면 좀더 편리하게 사용할 수 있다.
// utils/async-handler.js:
const asyncHandler = (requestHandler) => {
return async (req, res, next) => {
try {
await requestHandler(req, res);
} catch(err) {
next(err);
}
}
}
// 또는
const asyncHandler2 = fn => (req, res, next) => {
return Promise
.resolve(fn(req, res, next))
.catch(next);
};
module.exports = asyncHandler;
자바스크립트의 고차함수를 이용해서 인자로 라우트가 일치할 때 실행되는 HANDLER를 넘겨와 try-catch문 내부에서 실행시켜 매번 try-catch문을 작성하지 않아도 된다.
const { Router } = require('express');
const { Post } = require('../models');
const asyncHandler = require('../utils/async-handler');
const router = Router();
// 사용 전
//router.post('/', async (req, res, next) => {
// const { title, content } = req.body;
//
// try {
// if (!title || !content) {
// throw new Error('제목과 내용을 입력해 주세요');
// }
//
// const post = await Post.create({ title, content //});
// res.redirect(`/posts/${post.shortId}`);
// } catch (err) {
// next(err);
// }
//});
// 사용 후
router.post('/', asyncHandler(async (req, res) => {
const { title, content } = req.body;
if (!title || !content) {
throw new Error('제목과 내용을 입력해 주세요');
}
const post = await Post.create({ title, content });
res.redirect(`/posts/${post.shortId}`);
}));
이제는 Post document를 생성하는 create함수내부에 따로 try-catch문을 사용하지 않고 에러핸들링을 할 수 있다.