在节点中需要单例实例

时间:2014-09-09 14:46:51

标签: javascript node.js require

我在以下代码中窥探了以下内容:

var Log = require('log');

// This creates a singleton instance
module.exports = new Log('info');

我的第一反应是"不是单身"但我记得有一篇文章概述了Node.js如何require()语句说了一些关于缓存需要的语句并在后续使用它们调用

基本上我的问题是,导出new Object()实际上是在幕后创建单身?

我知道还有其他方法可以在JavaScript中创建单例,但这似乎是在Node内部实现它的一种非常方便的方法(如果它确实有效)。

3 个答案:

答案 0 :(得分:2)

是的,这是Node.js中最接近Singleton的东西。 require()在第一次调用时缓存每个模块,因此每个后续require()都返回相同的实例。

但是,您必须意识到这并不总是强制执行。可以修改/删除缓存,也可以使用其完整路径缓存模块,简而言之,这意味着如果您在包中定义单例并且您的包作为嵌套依赖项安装,则可能在您的“单例”中有多个实例同一应用程序的上下文。 快速举例:

Application
  node_modules
    PackageA
      node_modules
        YourPackageWithSingleton
    PackageB
      node_modules
        YourPackageWithSingleton

通常您不必担心这一点,但如果您确实需要在整个应用程序中共享一个对象,唯一的解决方案是使用全局(不鼓励)或依赖注入。

答案 1 :(得分:1)

由于您可以根据需要创建尽可能多的Log实例,因此它不是真正的单例。但你可以像这样使用它。否则,您只需通过var mySingleton = {}创建一个普通对象,并将属性和方法附加到它。

然后,您可以将mySingleton分配给module.exports,将require()分配给其他模块。

foo.js:

var mySingleton = {
    someMethod = function () {}
};

module.exports = mySingleton;

bar.js:

var singletonClass = require('./foo.js');

singletonClass.someMethod();

答案 2 :(得分:1)

为什么不亲自测试一下?

$ cat test.js
module.exports = Math.random();
$ node
> var a = require("./test");
undefined
> var a = require("./test");
undefined
> a === b
true

是的,似乎node.js确实缓存了导出的值。因此,如果您再次需要相同的模块,它将返回缓存的值,而不是创建新值。

但应注意,程序员可以require("log")手动创建新实例。所以从这个意义上来说,它不是一个单身人士。