【问题标题】:Can node modules require each other节点模块可以相互要求吗
【发布时间】:2014-06-14 01:06:51
【问题描述】:

我有以下 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 时,我会从 room.js 中的 'new User()' 得到一个 TypeError。似乎 room.js 中的用户被 index.js 中的用户隐藏了。

我做错了吗?允许这种要求吗?有任何想法吗?谢谢。

【问题讨论】:

    标签: javascript node.js node-modules


    【解决方案1】:

    查看http://nodejs.org/api/modules.html#modules_cycles 了解如何在 node.js 中进行处理。

    您可以通过多种方式解决您的问题,例如将依赖项传递给实例,即 依赖注入

    // 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();
    var room = new Room();
    

    像这样,您的导出是由您需要它们的时间定义的。

    但一般来说,如果你有循环依赖,你就做错了,应该考虑你的架构。 如果User 需要创建新的Rooms 而Room 需要创建新的Users,似乎他们俩的责任都太大了。 您可能需要第三个组件来负责创建正确的实例并将其传递给Room 和User,而不是让它们直接实例化这些实例。

    【讨论】:

    • 很好的答案。谢谢。重新架构似乎是最好的方法:)
    • 我不推荐第二个选项。因为,导入模块是一个同步任务。它可能会阻塞主线程。
    【解决方案2】:

    两者的区别:

    /* code above */
    function a() {};
    

    和

    /* code above */
    var a = function () {};
    

    在第一个示例中 a 是否将是 function 已经在 code above 中,但不是在第二个示例中。

    一旦你明白了,你就可以得出这个简单的解决方案:

    // 用户.js

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

    // room.js

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

    // index.js

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

    【讨论】:

      【解决方案3】:

      我认为有更好的方法来做到这一点。只需像这样切换导出和要求:

      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

      【讨论】:

      • 哇!自从创建www以来,这是我见过的最天才的东西,这应该是正确的答案,谢谢
      • 这似乎是一个很好的答案,但我已经重构了代码以从构造函数方法转到此方法,并且我不得不将看似无缘无故的bind() 扔到一些曾经可以工作的代码中。我没有花时间找到根本原因,但要小心..(this 未定义是传递成员函数作为参数时唯一明确的症状)。我确实喜欢这种方法,但这又浪费了一个小时......
      猜你喜欢
      • 2011-12-15
      • 2020-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 2018-11-30
      • 2019-07-31
      相关资源
      最近更新 更多