传递参数到require(在加载模块时)


113

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

我有提供登录功能的login.js模块。它需要数据库连接,并且我希望所有模块都使用相同的数据库连接。现在,我导出一个函数login.setDatabase(...),该函数可以让我指定数据库连接,并且可以正常工作。但是我宁愿在加载模块时传递数据库和其他要求。

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

我对NodeJS相当陌生,通常使用Java和Spring框架进行开发,所以是的……这是一个构造函数注入:)是否可以做类似我上面提供的代码的事情?


我还建议您查看问题的答案。正如我的回答所指出的,一个常见的习惯用法是将app对象传递给所需的模块。
大卫·韦尔登

您可以使用单例实现并在需要时调用db.getInstance(),而不是为db传递所有这些参数。
wulfgarpro

Answers:


236

根据您在此答案中的评论,我将执行以下操作:

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论点是必要的还是我可以省略?我的模块不会明确使用此应用程序参数,但是我不知道node.js是否需要某些内部操作。如果可以,我的模块声明将如下所示:module.exports = function (db) {
Ulysses Alves

这是Express应用程序特有的,因此绝对没有必要。
floatingLomas

@floatingLomas python中的序列化机制称为pickle:stackoverflow.com/questions/11218477/…–
SadSeven

1
那么,如果多次引用该模块会怎样?第一个require(mymodule)(myargs)将为您提供一个可使用的模块。但是,如果您从另一个模块中的其他地方引用它呢?在基本系统中,似乎包含一个缓存,但是在该系统中,该缓存将在随后对的调用中返回裸生成器方法require(),并且如果您将args传递给require()(someargs)您,则会得到另一个模块...也许我丢失了某物
汤姆H

2
@TomH在这种情况下,您需要对其进行缓存。为此,您需要var module;在exports函数之外,然后在进入后立即检查是否module已定义,如果已定义,则将其返回(如果没有,则对其进行初始化)。那有意义吗?
floatingLomas

37

我不确定这是否仍然对人们有用,但是有了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 )

32

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

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

1
我尝试了这个。在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可能不是您想要的。如果要使用原始问题中的模式,则最好将其保留为单个导出值。如果仍然没有道理,我建议您发布要点以供参考。
David Weldon

1
再次阅读此内容后,听起来您可能已被分配authexports对象的属性,然后又在模块中将其分配exports给一个函数(因此将覆盖先前的分配)。如果您颠倒分配的顺序,则应该能够按auth预期访问该功能。同样,如果没有实际看到代码,很难说出来。
David Weldon

1
非常感谢你的帮助。我没有意识到的正是您使用require('login')。auth的目标。我虽然有中没有差异var login = require('login')var login = require('login')(app),但有一个巨大的差异,存在返回的匿名函数没有魔法,它只是另一个函数/对象。module.exports.auth现在,anomymous函数代替了a ,而不是使用auth函数(包括auth函数)return { auth: authFunction, login: loginFunction}。所以现在可以了。谢谢。
安德烈亚斯·塞伦沃尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.