Exigir retorna um objeto vazio


125

Eu tenho uma pasta que tem index.js e alguns modelos (classes) 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

O problema é que a classe Author parece não encontrar o livro! É apenas um objeto vazio. No entanto, se eu alternar as exportações no index.js, colocar Livro após autor - ele funciona, mas o outro modelo para de funcionar.

Não quero fazer hacks para fazer funcionar.


4
Author.js precisa de Book.js para ser executado, e Book.js precisa de Author.js para ser executado? Remova a dependência circular.
— Philipp Gayret 26/05

1
Que objeto ActiveRecord é esse? De onde é?
— BT

Respostas:


207

Isso ocorre porque você tem uma dependência circular. O Node.js lida com isso de uma maneira muito específica:

  1. O primeiro módulo é carregado e executado (neste caso book.js). Ele ( book.js) carregará e executará o segundo módulo ( author.js) quando ( book.js) exigir o outro ( author.js)

  2. Quando o segundo módulo ( author.js) é carregado e executado, ele ( author.js) requer o primeiro módulo ( book.js), mas ( author.js) recebe um objeto parcialmente preenchido - no entanto, muitas coisas foram definidas nas exportações em book.js antes de requerer author.js estar nesse objeto

  3. Após a book.jsexecução completa, o objeto author.jsobtido require('./book')será o book.jsobjeto do módulo completo

Para mais informações, veja os documentos: http://nodejs.org/api/modules.html

Se for possível adicionar dinamicamente esse esquema a um desses objetos do ActiveRecord, é uma maneira de resolver isso. Essa é realmente uma situação complicada. De fato, mesmo sem o sistema do módulo, isso causaria problemas para você. Se você colocasse todo esse código em um arquivo, como faria isso funcionar?


1
Eu sei que você não deve colocar tudo em um arquivo, mas estou dizendo que é apenas uma experiência assim. O que quero dizer é que não é o sistema de módulos do node.js. que está causando o problema aqui, é o próprio código.
— BT

De fato, Java tem os mesmos problemas com dependências circulares - é um problema que qualquer linguagem pode ter. Se tudo o que você precisa é uma referência ao seu parceiro de dependência circular, o javascript pode fazer isso tão facilmente quanto o java. No entanto, aqui, você está tentando usar o objeto antes de ser construído (em extensão)
— BT

Sim, na verdade agora eu entendi. Nunca veio à mente. Então, só há uma maneira - adicioná-lo dinamicamente, eu acho. Ou passando um nome de modelo como uma sequência. Obrigado pela sua resposta!
— User3677173

18
Eu recomendo Madge para depurar esse tipo de problemas em casos mais complexos (ou seja, com mais arquivos). Uma vez instalado, você pode usar madge -c <app entry point>para detectar quaisquer dependências circulares.
— precisa saber é

7
Obrigado. Bastante doloroso que ele nem gere um erro, mas apenas retorna um objeto vazio.
— Robert Oschler
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.