まさたか日記スマートフォン用の表示で見るまさたか日記2013-09-19Node.jsの例外処理(ドメインの存在意義)TypeScript/NodeNode.jsはエコシステムが発達していて、コアライブラリだけでなく、サードパーティがたくさん有用な拡張モジュールを提供してくれています。自前で書くコードも一つのJSファイルだけで書くのではなく、見通しも良いように、再利用可能なように、機能単位毎にモジュールにまとめて作って行くべきでしょう。その際、ライブラリ的なモジュールでは具体的に実行時例外の処理をすべきではないのが一般的だと思います。例外処理をおこなって例外握りつぶしちゃうと問題が内部で起きている事をアプリケーションレベルできちんと把握できなくなっちゃう。Node.jsのライブラリ作法としては、例外をそのままthrowするのとは別に、下記の書き方があります(以下、冗長なのでモジュール分割しないで書いてますが...)。Error)をもって例外を通知する仕組みが合理的です。try-catch文はtryブロックに続けてcatchブロックを文法的制約上tryとcatchを一対かつ一箇所で書かないといけないのですが、EventEmitterを利用すると、別途に用意したイベントハンドラにて集約処理ができるので、保護したいブロック多数に対して例外処理ブロックを少数かつ違う場所で書けます。上記例では末尾にてfireError()を立て続けに何度も呼び出していますが、これは他所で五月雨に呼び出してもOKなのです。emitter2.fireError();ドメイン使って書くとこんな感じ。EventEmitterにて書いてた例外処理ブロックをさらにドメインに集約することができますので、複数のEventEmitterを一つのドメインで処理できます。EventEmitterのドメインへの登録は、コンストラクタがDomain#bind()/#run()/#intercept()の引数に渡される関数内に書かれているときには自動的に参加します。EventEmitterコンストラクタで参加ロジックが記述されているので、EventEmitterをプロトタイプ継承させる場合は、以下のような処理が絶対必要。//これはNode.jsの定番な書き方emitter2の方は、Domain#add()でドメイン参加させています。アプリケーションコードでは無いところでコンストラクタの呼び出しがあった場合に用いられます。d.run(next);});express〜connectのミドルウェアの中でドメイン使うとすると、Domain#run()する前に引数で渡されてくるreqおよびresは作られちゃっている。このreqおよびresはEventEmitterの果ての子孫なのでこういう感じで。ミドルウェアの中でonハンドラ書いているのは、reqとresが直接見えるためで、たぶんこうしていいのだと思うけど、よりよいやり方があるかもしれない。このほか、先にNode.jsのコードを見てきたように、コールバックやTimer系関数はいちいちドメインに対応しているのできちんとDomain#run()を使ってあげるとイベントループによるコールスタックの断絶にも関わらずきちんと例外補足してくれます。まとめ:Domain#run()/bind()で保護する。try-catchと異なりprocess.nextTick()やTimer系でもOK。Domain#run()/bind()で保護できないときにはDomain#add()Domain#on('error')で例外処理を書くモジュールではEventEmitter#emit('error')を活用してみる。Technology(米国)はてなブログをはじめよう!masataka_kさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。