【问题标题】:Passing arguments to require (when loading module)将参数传递给要求(加载模块时)
【发布时间】:2012-10-20 13:00:42
【问题描述】:

使用 require 加载模块时是否可以传递参数?

我有提供登录功能的模块 login.js。它需要一个数据库连接,我希望在我的所有模块中使用相同的数据库连接。现在我导出一个函数 login.setDatabase(...) 让我指定一个数据库连接,它工作得很好。但我宁愿在加载模块时传递数据库和任何其他要求。

var db = ...
var login = require("./login.js")(db);

我是 NodeJS 的新手,通常使用 Java 和 Spring 框架进行开发,所以是的...这是一个构造函数注入 :) 是否可以执行类似于我上面提供的代码的操作?

【问题讨论】:

  • 我还建议查看this 问题的答案。正如我在回答中所指出的,一个常见的习惯是将 app 对象传递给所需的模块。
  • 您可以使用singleton 实现并在需要时调用 db.getInstance(),而不是为 db 传递所有这些参数。
  • 使用db作为导出文件中函数的参数

标签: node.js express


【解决方案1】:

根据您在this answer 中的 cmets,我会按照您的要求做这样的事情:

module.exports = function (app, db) {
    var module = {};

    module.auth = function (req, res) {
        // This will be available 'outside'.
        // Authy stuff that can be used outside...
    };

    // Other stuff...
    module.pickle = function(cucumber, herbs, vinegar) {
        // This will be available 'outside'.
        // Pickling stuff...
    };

    function jarThemPickles(pickle, jar) {
        // This will be NOT available 'outside'.
        // Pickling stuff...

        return pickleJar;
    };

    return module;
};

我几乎所有的模块都是这样构建的。似乎对我很有效。

【讨论】:

  • app 参数是必要的还是我可以省略它?我的模块不会明确使用这个 app 参数,但我不知道 node.js 是否需要它来处理一些内部事情。如果没问题,我的模块声明将如下所示:module.exports = function (db) {
  • 这是特定于 Express 应用程序的,因此绝对没有必要。
  • @floatingLomas python中的序列化机制叫做pickle:stackoverflow.com/questions/11218477/…
  • 那么如果你多次引用该模块会发生什么?第一个require(mymodule)(myargs) 将为您提供一个可以使用的模块。但是,如果您从另一个模块的其他地方引用它?在基本系统中似乎涉及到一个缓存,但在这个系统中,缓存将在后续调用require() 时返回裸生成器方法,如果您将参数传递给require()(someargs),您将得到一个不同的模块。 ..也许我错过了什么
  • @TomH 在这种情况下,您需要缓存它。要做到这一点,您将在导出函数之外拥有var module;,然后一旦您进入,您就想检查module 是否已经定义,如果是,则返回它(如果没有,初始化它)。这有意义吗?
【解决方案2】:

我不确定这是否仍然对人们有用,但是使用 ES6,我有一种方法可以做到这一点,我觉得它既干净又有用。

class MyClass { 
  constructor ( arg1, arg2, arg3 )
  myFunction1 () {...}
  myFunction2 () {...}
  myFunction3 () {...}
}

module.exports = ( arg1, arg2, arg3 ) => { return new MyClass( arg1,arg2,arg3 ) }

然后您会得到预期的行为。

var MyClass = require('/MyClass.js')( arg1, arg2, arg3 )

【讨论】:

    【解决方案3】:

    是的。在您的login 模块中,只需导出一个以db 作为参数的函数。例如:

    module.exports = function(db) {
      ...
    };
    

    【讨论】:

    • 我试过了。在 login.js module.exports = function(app,db) { ... } module.exports.auth = function(req,res) { ... authentication stuff } 它确实调用了“匿名”函数并设置了 appdb 变量,但是,这样做时我的应用程序将找不到 auth 函数。我究竟做错了什么?如果我删除匿名函数,auth 函数将再次可访问。
    • 就像 javascript 中的所有内容一样,exports 是一个对象。您可以为其分配属性(多个导出),也可以将其分配给一个值。听起来您将导出分配给了一个函数,但随后将 auth 分配为您分配给导出的函数的属性。所以你需要做var auth = require("./login.js").auth 这可能不是你想要的。如果您想使用原始问题中的模式,最好坚持使用单个导出值。如果这仍然没有意义,我建议发布一个要点供我查看。
    • 再读一遍,听起来您可能已经将auth 分配为exports 对象的属性,然后在模块中您将exports 分配给函数(因此覆盖之前的任务)。如果您颠倒分配的顺序,您应该能够按预期访问auth 函数。再一次,如果没有实际看到代码,就很难分辨。
    • 非常感谢您的帮助。我没有意识到这正是您使用 require('login').auth 的目标。我虽然var login = require('login')var login = require('login')(app) 没有区别,但是有很大的区别,返回的匿名函数没有魔法,它只是另一个函数/对象。 anomymous 函数现在返回 auth 函数(以及其他函数),而不是 module.exports.auth,即 return { auth: authFunction, login: loginFunction}。所以现在它可以工作了。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多