如何在快速路线中引用模块

时间:2016-07-04 17:07:23

标签: node.js express

我希望将快速路由放在单独的文件中,但我很难确定在路由中引用模块的最佳做法是什么。

以下是我在下面看到的各种方法。哪一个是最佳做法?根据您的尝试(日志记录,配置,数据源等),这是否会发生变化?

请注意,为了缩短发布时间,这些差距很小。

  1. "需要"在应用和路线中。
  2. //app.js
    var cfg = require('./config.js');
    
    //router.js
    var cfg = require('./config.js');
    
    module.exports = function () {
    
        var router = new express.Router();
    
        router.get('/search', function(req, res) {
            console.log('cfg', cfg);
        });
    
        return router;
    };
    
    1. 进入模块
    2. //app.js
      var cfg = require('./config.js');
      app.use(require('./router')(cfg));
      
      //router.js
      module.exports = function (cfg) {
      
          var router = new express.Router();
      
          router.get('/search', function(req, res) {
              console.log('cfg', cfg);
          });
      
          return router;
      };
      
      1. 使用express app.set / get
      2. //app.js
        var cfg = require('./config.js');
        app.set('cfg', cfg);
        
        //router.js
        module.exports = function () {
        
            var router = new express.Router();
        
            router.get('/search', function(req, res) {
                console.log('cfg', app.get('cfg'));
            });
        
            return router;
        };
        
        1. 使用快速中间件并添加到req
        2. //app.js
          var cfg = require('./config.js');
          
          app.use(function (req, res, next) {
            req.cfg = cfg;
            next();
          });
          
          //router.js
          module.exports = function () {
          
              var router = new express.Router();
          
              router.get('/search', function(req, res) {
                  console.log('cfg', req.cfg);
              });
          
              return router;
          };
          

2 个答案:

答案 0 :(得分:2)

node.js中的模块设计实际上取决于您对模块的目标。

我通常开始认为模块应该尽可能可重复使用,而不会使设计扭曲或复杂化,超出可能需要的范围。有时,只需以可重用的方式组织代码就不需要额外的工作。有时您会发现可重复使用的通用方案需要更多的工作或复杂功能。如果它最终需要更多的工作,并且您重复使用该模块的可能性很低,那么如果您不尝试使其通常可重用,那么您的代码实际上可能更简单,更好。所以,无论如何,这里的要点是你必须弄清楚模块的目标是什么,然后你可以根据这个目标做出设计决策。

如果模块设计为可以在其他应用程序中独立使用,那么模块应该尽可能独立。这意味着它应该require()在它需要的一切(你的选项1)中,或者它应该清楚地记录需要传递给模块构造函数的东西(你的选项2)。这将允许模块在其他项目中使用,而不必成为复杂环境的一部分(全局,应用程序配置等......)。

模块可重用性的核心原则是使它们尽可能独立且易于使用。无论您是在配置模块中需要还是将配置对象传递给构造函数,都取决于您是否想要调用者能够管理配置对象本身而不是让模块从其自己的位置加载配置对象。这是一个取决于您的设计目标的设计决定。

如果由于某种原因,该模块无法在其他应用程序中使用,并且您在规划中没有任何好处,那么设计模块就可以完全正确某个环境将出现在您的应用程序中。这可能包括您的选项3(app.set / get)或4(中间件cfg)。就个人而言,我会避免中间件方案只是因为我试图避免添加适用于每个请求的工作,只有一些路由可能需要该信息。这里的工作并不多,但从概念上讲,我并不想让req对象成为每个可能的请求处理程序可能需要的所有内容的联合。我希望代码更具体,路由使用app.get()在需要时获取配置。但是,要么可以正常工作。

P.S。我不会使用评论中的global.cfg建议。这立即与任何其他模块不兼容,该模块也决定使用global.cfg用于其自身目的,这正是我们避免全局变量的原因。

app.get/set与全局变量类似,但是如果您拥有app对象,那么您可以控制其命名空间,并且您不应该找到使用相同命名空间的随机其他模块,因此它&# 39;比实际全局变量更好的情况。事实上,除非你先给他们app对象,否则没有其他代码可以使用它(这就是为什么它们实际上不是全局的)。

答案 1 :(得分:0)

我肯定会说“这取决于你究竟想要传递给路线的是什么。”

  1. 我会将此方法用于实用程序或全局模块(例如lodash或类似的,或提供应用程序配置的模块)。这允许路由仅需要模块(如果它实际上在此路由中使用)。
  2. 我会将此方法用于在应用程序级别创建的某些对象,并且您需要确保在整个应用程序中使用相同的实例(例如,数据库连接提供程序对象或类似对象)。当您添加更多对象时,这会影响您必须在路径文件中导出的函数的签名,因此您可能希望保持此列表相对较短,并确保所有或至少大多数路径都使用这些对象。 / LI>
  3. 我实际上从未使用过这个,但看起来这应该用于设置与express相关的配置。
  4. 我会使用这种方法来设置与一个特定请求相关的属性(例如,如果您有一个身份验证中间件,您可以将当前登录的用户设置为这样的请求,以便以下中间件可以访问它)。这增加了为每个请求执行的中间件,这可能会在应用程序增长时增加一些不必要的开销,并且您有越来越多的对象需要传递到路由中。