Requireは空のオブジェクトを返します


125

index.jsといくつかのモデル(クラス)index.jsがあるフォルダーがあります

module.exports = {
   Book : require('./book'),
   Author : require('./author')
}

book.js

var Author = require('./author')
var Book = models.ActiveRecord.extend({
    schema : {
        belongsTo : {
            author : Author
        }
    }
})
module.exports = Book

author.js

var Book = require('./book')
var Author = models.ActiveRecord.extend({
    schema : {
        hasMany : {
            author : Book
        }
    }
})

module.exports = Author

問題は、AuthorクラスがBookを見つけられないように見えることです。それはただの空のオブジェクトです。ただし、index.jsでエクスポートを切り替えて、Authorの後にBookを配置すると、機能しますが、他のモデルは機能しなくなります。

私はそれを機能させるためにハッキングをしたくありません。


4
Author.jsはBook.jsを実行する必要があり、Book.jsはAuthor.jsを実行する必要がありますか?循環依存関係を削除します。
— Philipp Gayret 2014年

1
それはどんなActiveRecordオブジェクトですか?これ、どこから来たの?
— BT 2014年

回答:


207

これは循環依存関係があるためです。Node.jsはこれを非常に特殊な方法で処理します。

  1. 最初のモジュールが読み込まれて実行されます(この場合はbook.js)。それは(book.js)(第二のモジュールをロードして実行するauthor.js、それが(とき)book.js)(他が必要ですauthor.js)

  2. 2番目のモジュール(author.js)が読み込まれて実行されるとauthor.js、最初のモジュール(book.js)が必要ですが()author.jsは部分的に埋められたオブジェクトを受け取ります。そのオブジェクトの中にいる

  3. 後にbook.js完全に介して実行され、対象物author.jsから得がrequire('./book')いっぱいになるbook.jsモジュールオブジェクト

詳しくは、こちらのドキュメントをご覧ください。http://nodejs.org/api/modules.html

それらのActiveRecordオブジェクトの1つにそのスキーマを動的に追加することが可能であれば、それはこれを解決する1つの方法です。これは実際には一種のトリッキーな状況です。実際、モジュールシステムがなくても、問題が発生します。このすべてのコードを1つのファイルに入れる場合、どのように機能させるのでしょうか。


1
すべてを1つのファイルに入れてはいけないことはわかっていますが、そのように実験するだけです。ここで問題を引き起こしているのはnode.jsのモジュールシステムではなく、コード自体です。
— BT 2014年

そして実際のところ、Javaには循環依存関係と同じ問題があります-それはどの言語にも起こり得る問題です。必要なのが循環依存パートナーへの参照だけである場合、javascriptはjavaと同じくらい簡単にそれを行うことができます。ただし、ここでは、オブジェクトが構築される前に(
— BT

ええ、実際に私はそれを理解しました。思い浮かばなかった。したがって、動的に追加する方法は1つしかありません。または、モデル名を文字列として渡します。御返答いただき有難うございます!
— user3677173 2014年

18
より複雑なケース(つまり、ファイル数が多い)でこの種の問題をデバッグする場合は、Madgeを強くお勧めします。インストールしたらmadge -c <app entry point>、循環依存関係の検出に使用できます。
— schu34

7
ありがとう。エラーをスローすることさえなく、空のオブジェクトを返すだけでかなり痛いです。
— ロバートオシュラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.