Promiseのcatchで例外を投げてもExpressがハンドリングしてくれなかった。
以下がreject側のコード。
TypeScriptです。
public static signup(userName: string, userPassword: string): Promise<User> { return new Promise<User>( (resolve, reject) => { const db1Master: DbMasterConnection = DbConnector.createInstance().createMaster(DbType.DB1); UserRepo.findByName(userName, db1Master).then( (user: User) => { if(user.isEmpty() === false){ //ユーザーが存在しているので例外 reject(AppException.createError(AppErrorRegistry.DB_CONNECTION_ERROR)); }else{ //とりあえず resolve resolve(Promise.resolve(new User(100000, 'test', 'test', new RecordTime()))); } }); }); }
以下がcatch側のコード。
router.post('/add', function(req, res, next) { LoginApplication.signup(req.body.user_name, req.body.user_password).then( (user: User) => { //正常処理 res.redirect('/'); }).catch( (err) => { //エラー throw err; }); });
catch() 内の throw err でExpressのエラーハンドリングに拾われると思ったけど、
拾われなかった。
問題はcatch側のコードにあった。
修正したものが以下。
router.post('/add', function(req, res, next) { LoginApplication.signup(req.body.user_name, req.body.user_password).then( (user: User) => { //正常処理 res.redirect('/'); }).catch( (err) => { //エラー next(err); }); });
catch内の next(err) が修正箇所。
ドキュメントの http://expressjs.com/guide/routing.html の Route handlers を確認したところ、
Expressの next() は処理を他のミドルウェアに委譲する関数らしい。
で、エラーハンドリングは app.js で以下のように設定されている。
app.use(function(err: any, req, res, next) { res.status(err['status'] || 500); res.render('error', { message: err.message, error: err }); });
多分、このエラーハンドリングがrouterのnext()で呼ばれるんだと思う。