プログラムエラーが出た時に、そのままにしていると夜も眠れなくなる、ユゲタです。
今日は現在開発をしている、Nodejs系フレームワークで、不意に出たエラーで半日ほど費やしてしまったという話をビボっておきたいと思います。
出たエラーの詳細
Nodejsでhttpサーバーを立ち上げて、その中で任意に作ったプログラムファイルを実行するという少し複雑な処理をしている時に発生したエラーです。
まずは、表示されたエラーは次のようなものです。(※関数名などは#...文字に置き換えてあります)
TypeError: status.load is not a function
at Object.# errorの出たfunction名 (## errorの出たファイルパスと行数)
(node:39593) Warning: Accessing non-existent property ‘## ‘エラーが出た関数 of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
おそらく、このページを見ている人は、このエラー内容でググって何かしらヒットしたのではないかと思いますが、
Nodeのエラーコードって、ファイル名とその対象行数が表示されているので、結構対応が簡単だったのですが、これは任意のモジュール(jsファイル)を読み込んで、その中に書き込まれているはずのfunctionがundefined(見つからない)という内容でした。
でも、ちゃんと、そのモジュール内にfunctionが書き込まれているし、他のモジュールは同じ構造なので、全く問題なく実行できている・・・
これ、どういうこと???という事で、ここから数時間の長い「console.logを書いて戻り値確認」という闘いが始まりました。
原因
こういう原因が掴みづらいエラーは、思考を変えてみると、フトしたタイミングですんなり直る事が多いのですが、
今回のエラーの原因は、読み込まれたモジュールで、読み込み元のモジュールを読み込む処理を書き込んでしまっていたために、相互読み込みで無限処理に繋がっているというエラーだったんですね。
よく見たら、エラー文面に次のように書かれていました・・・
module exports inside circular dependency
翻訳)モジュールは循環依存内にエクスポートします
一時期は、nodejsを再インストールする勢いで、必死に確認作業を行っていたのですが、なんとも恥ずかしい結末でした。
でも、エラー対応ってこんなもんなんですよね。
対策
とりあえず、今回のエラーを整理すると、読み込み元のモジュールAから、今回エラーが出たモジュールBを読み込んだ際に、モジュールBにモジュールAのrequireが書き込まれていたという内容だったので、
簡単にそれぞれのモジュールの役割を書いてみると
モジュールA : データベースとのやり取りをして、返り値を整形する処理
モジュールB : 部分的なリストを取得する処理
この時に、モジュールBは、別データとのリレーションを参照する時にモジュールAを読み込んでしまっていたんですね。
とりあえずの対応ということで、モジュールBをモジュールA内に移して、相互読み込み状態を解消しました。
まとめ
同じエラーで困っている人、エラー内に「循環依存」という単語が書かれているので、今一度モジュール構成を見直してみてください。
エラー文をちゃんと読むという事も重要だけど、そもそものプログラム設計がまだまだ整っていないな〜と、改めていきあたりばったりの自分流プログラミングを感じてしまいました。
でも、まあ、こういう事を繰り返していくことで、堅牢なプログラミングが出来上がっていくことも合わせて重要だということを体験した本日のエラー対応でした。
さて、引き続き便利なフレームワーク開発を続けるとするか!
0 件のコメント:
コメントを投稿