async/awaitが利用できるようになって非同期処理の例外もキャッチできるようになりましたが、それなりの規模のアプリケーションを作成するにあたり、どのように例外処理を行えばよいか迷っています。
例えば以下はKoaを利用したウェブアプリケーションの例になりますが、catchで受け取ったエラーオブジェクトを判定してエラーの種類によって適切な処理に振り分けるようなことをするのが一般的だと認識しています。
const Koa = require('koa') const app = new Koa() app.use(async (ctx, next) => { try { await next() } catch(e) { // エラーインスタンスの種類を判定して適切に処理 if (e instanceof TypeError || e instanceof RangeError || e instanceof EvalError) { ctx.state = 500 } } })
上記のように標準のエラーを振り分ける場合はこれでよいと思っているのですが「アクセス権限が無い」といったエラーを独自に作成する場合には以下のようにする必要があると思います。
const Koa = require('koa') const app = new Koa() app.use(async (ctx, next) => { try { await next() } catch(e) { // 標準エラーを適切に処理 if (e instanceof TypeError || e instanceof RangeError || e instanceof EvalError) { ctx.state = 500 // 認証エラーを適切に処理 } else if (e instanceof AuthError) { ctx.state = 403 } } }) // -------------------------------- const AuthError = require('AuthError') app.use((ctx, next) => { ... if( !isAdmin ) throw new AuthError() })
しかし私はこのようにエラー処理を行っている例を見たことが無いので、本当にこれでよいのか不安です。
調べてみたところほとんどのサンプルではエラーを以下のように投げていました。
throw new Error('auth error')
しかしこうしてしまうとキャッチしたエラーを種類別に判定することができなくなってしまいますよね?
もちろんe.message
の内容を利用することでエラー別に適切な処理を行うことは不可能では無いと思っていますが、エラーメッセージは同じエラーでも内容が変わってしまうことがあると思うんです。
// 1234の値が状況によって変わるのでe.massegeをエラー種類判定に使えない console.log(e.message) // "user 1234 is not found"
そのため、エラーの種類ごとに新しいエラークラスを作成してそのインスタンスを投げる方法しかないのだろうと思っているのですが、正直なところ大量のエラークラスを作成するのは面倒な作業だなと思っています。そこで、以下のように処理してしまえばいいのでは?と思いました。
const Koa = require('koa') const app = new Koa() app.use(async (ctx, next) => { try { await next() } catch(e) { // 標準エラーを適切に処理 if (e.name == 'TypeError' || e.name == 'RangeError' || e.name == 'EvalError') { ctx.state = 500 // 認証エラーを適切に処理 } else if (e.name == 'AuthError') { ctx.state = 403 } } }) // -------------------------------- app.use((ctx, next) => { ... if( !isAdmin ) { let e = new Error('auth error') e.name = 'AuthError' throw e } })
上記の方法ではe.name
の内容を書き換える必要があるのでカスマムエラークラスを作成していた時と比較して1行でエラーをthrowすることができていた部分が4行に膨れ上がっているため若干不満ですが、それ以外は満足のいくものになりました。
よし、これでいこう!と思ったのですが、本当にこれでいいのだろうか?皆様はどのように例外処理を行なっているのだろうということが気になって前に進むことができません。
本当にこのような方法で例外処理をしてもよいのでしょうか?
例えば、このようなe.name
を書き換える方法を使って例外を投げるモジュールを作成した場合、そのモジュールが、他のプロジェクトで利用することになった場合に問題は発生しないのだろうか?という新たな疑問が発生しました。
そもそも、一般的に例外処理はどのように行えばよいのでしょうか?
検索したのですが、あまりにも記事が出てこないので質問させていただきました。
よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/03/23 23:23
2017/03/24 06:34
2017/03/24 06:56