読者です 読者をやめる 読者になる 読者になる

Express4 + Promise + エラーハンドリング

Node.js

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()で呼ばれるんだと思う。