blog

エレガント|koa 例外を処理する

良いコーディング習慣は例外処理と切っても切り離せないものですが、この記事では、以下のkoaフレームワークのエラーの投げ方と、戻り例外の統一的な処理方法を紹介します。 koaは、優れたNodeJsのWe...

Oct 22, 2020 · 3 min. read
シェア

良いコーディングの習慣は例外処理と切っても切り離せないものですが、この記事では、以下のkoaフレームワークのエラーの投げ方と、戻り例外の統一的な処理方法について紹介します。

通常のエラー処理

koaは優れたNodeJsのWebフレームワークですが、Webプロジェクトの開発では、httpエラーやカスタムビジネスロジックの処理を含む、任意のエラー処理を避けることはできません。Node.jsでは、エラーは次のようにスローされます。

if(someCondition){
	throw Error("Error");
}

Httpエラー処理

ここではctx.throw(400)を使って、httpエラーを投げると同時にいくつかの情報を返しています。

ctx.status = 400
ctx.body = {
	msg: "some params is invalid"
}

この時点で、ステータスコードと関連するエラーメッセージの両方が返されます。

ビジネスロジックのエラー処理

Restful APIサーバーを開発する必要がある場合、今度は以下のようなビジネスロジックのエラーコードを定義する必要があります。

0 success
-1 server error
0041 token

今回はビジネス・レイヤーで処理する必要があります。

router.get("/", (ctx, next) => {
	if(tokenExpire(token)){
		const errcode = ERROR_CODE.TOKEN_EXPIRED;
		ctx.body = {
			errcode,
			msg: ERROR_MSG[errcode]
		}
		return
	}
})

ここでは、該当するエラーコードがerrcode

グローバルキャッチ例外処理

koa では、例外はグローバルに捕捉され、例外を確実に捕捉するためにミドルウェアが使用されます。例外を捕捉するために、catcherror ミドルウェアがミドルウェアに組み込まれています。

// middlewares/catcherror.js
const catchError = async(ctx, next) => {
	try{
		await next();
	}catch(error){
		if(error.errorCode){
			console.log("例外をキャッチする")
			return ctx.body = errror.msg;
		}
	}
}
module.exports = catchError

これはミドルウェアを定義し、ミドルウェア内で関連するキャッチを行い、関連する例外が確実にキャッチされるようにし、このミドルウェアをエクスポートします。

nextの内部では、次のプログラムに例外が発生した場合、ミドルウェアで該当するcatchを実現できます。

const koa = require("koa")
const Router = require("router")
const app = new koa();
const router = new Router();
const catchError = require("./middlewares/catcherror")
app.use(catchError)
router.get('/login', (ctx, next) => {
	const path = ctx.request.query;
	
	// 積極的にエラーを投げる
	if(true){
		const error = new Error();
		error.errorCode = 1000;
		error.msg = " ;
		throw error
	}
})
app.use(router.routers())
app.listen(3000)

今回はミドルウェアのおかげで、エラー例外を投げる実装が可能です。

基本クラスを使った処理

能動的にエラーを投げるのはかなり面倒なので、ここではエラークラスを継承することでオブジェクト指向のアプローチを使っています。エラー情報をエラークラスに入れることで、エラーが直接投げられるようになります。

// core/http-exception.js
class HttpException extends Error{
	constructor(msg = 'サーバーの例外', errorCode = 1000. code = 400){
		super();
		this.msg = msg;
		this.code = code;
		this.errorCode = errorCode;
	}
}
module.export = HttpException

app.jsの書き直し

// app.js
const koa = require('koa')
const Router = require('router')
const app = new koa()
const router = new Router()
const {HttpException} = require('../core/http-exception')
const catchError = require('./middlewares/catcherror')
app.use(catchError) //最初のミドルウェア
router.get('/login',(ctx,next)=>{
 const path = ctx.request.query
 
 // 積極的にエラーを投げる
 if(true){
		// ここでの主な書き換えは、新しい例外を作ることだ。
 const error = new HttpException('ログインエラー',0)
 throw error
 }
})
app.use(router.routes())
app.listen(3000)

ミドルウェアをもう一度書き直し、例外がこの例外のオブジェクトに属するかどうかを判断します。

// middlewares/catcherror.js
const {HttpException} = require('../core/http-exception')
const catchEoore = async (ctx,next)=>{
 try{
 await next()
 } catch(error){
 if(error instanceof HttpExcetion){
 return ctx.body = error.msg
 }
 }
 }
}
module.exports = catchError

これで書き換え完了。

Read next

再入可能ロック解除処理のソースコード詳細

unparkingプロセスは、パークが解除されるプロセスであるため、理解する必要があります。前のドキュメントでは、ロック

Oct 22, 2020 · 4 min read