Могут ли модули node требовать друг друга

У меня есть следующие 3 файла.

user.js требует, чтобы room.js и room.js требовали user.js.

user.js

var Room = require('./room.js');

var User = function () {};
User.prototype.test = function () {
  return new Room();
};

module.exports = User;

room.js

var User = require('./user.js');

var Room = function () {};
Room.prototype.test = function () {
  return new User();
};

module.exports = Room;

index.js

var User = require('./user.js');
var Room = require('./room.js');

var user = new User();
var room = new Room();

user.test();
room.test();

index.js требует как комнаты, так и пользователя.

Вот проблема. Когда я запустил index.js, я получу TypeError из 'new User()' в room.js. Кажется, что Пользователь в room.js скрыт пользователем в index.js.

Я делаю что-то неправильно? Разрешено ли это разрешение? Есть идеи? Спасибо.

Ответы

Ответ 1

Ознакомьтесь с http://nodejs.org/api/modules.html#modules_cycles, как это описано в node.

Вы можете решить свои проблемы несколькими способами, например, передавать в зависимостях экземпляры aka Dependency Injection

// user.js
var User = function (Room) { this.Room = Room; };
User.prototype.test = function () {
  return new this.Room();
};
module.exports = User;

// room.js
var Room = function (User) { this.User = User; };
Room.prototype.test = function () {
  return new this.User();
};
module.exports = Room;

// index.js
var User = require('./user.js');
var Room = require('./room.js');

var user = new User(Room);
var room = new Room(User);

Другим способом было бы требовать файлы только тогда, когда они вам нужны.

// user.js
var User = function () {};
User.prototype.test = function () {
  var Room = require('./room');
  return new Room();
};
module.exports = User;


// room.js
var Room = function () {};
Room.prototype.test = function () {
  var User = require('./user');
  return new User();
};
module.exports = Room;

// index.js
var User = require('./user.js');
var Room = require('./room.js');

var user = new User(Room);
var room = new Room(User);

Таким образом, ваш экспорт определяется по мере необходимости.

Но в целом, если у вас есть круговые зависимости, вы делаете что-то неправильно и должны думать о своей архитектуре. Если a User необходимо создать новый Rooms, а Room необходимо создать новый Users, похоже, что у них обоих слишком большая ответственность. Возможно, вам понадобится третий компонент, который отвечает за создание и передачу правильных экземпляров в Room и User, вместо того, чтобы создавать их непосредственно.

Ответ 2

Я думаю, что есть намного лучший способ, как это сделать. Просто переключите экспорт и выполните следующие действия:

user.js

var User = function () {};
module.exports = User;    

User.prototype.test = function () {
    return new Room();
};

var Room = require('./room.js');

room.js

var Room = function () {};
module.exports = Room;    

Room.prototype.test = function () {
  return new User();
};

var User = require('./user.js');

index.js

var User = require('./user.js');
var Room = require('./room.js');

var user = new User();
var room = new Room();

user.test();
room.test();

проверьте эту статью: https://coderwall.com/p/myzvmg/circular-dependencies-in-node-js