节点中需要Singleton实例

Requiring Singleton Instances in Node

本文关键字:Singleton 实例 节点      更新时间:2023-09-26

我在一些代码中发现了以下内容:

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

我的第一反应是"不可能是singleton",但我记得有一篇文章概述了Node.js如何执行require()语句,其中谈到了缓存require语句并在随后的调用中使用它们。

所以基本上我的问题是,导出一个new Object()实际上是在幕后创建一个单例吗?

我知道在JavaScript中还有其他创建singleton的方法,但这似乎是在Node中实现这一点的一种非常方便的方法(如果它真的有效的话)。

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

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

Application
  node_modules
    PackageA
      node_modules
        YourPackageWithSingleton
    PackageB
      node_modules
        YourPackageWithSingleton

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

它实际上不是一个单例,因为您可以创建任意多的Log实例。但是你可以这样使用它。否则,您只需通过var mySingleton = {}创建一个普通对象,并为其附加属性和方法

然后您可以在其他模块中将mySingleton分配给module.exportsrequire()

foo.js:

var mySingleton = {
    someMethod = function () {}
};
module.exports = mySingleton;

bar.js:

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

为什么不自己测试一下呢?

$ 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")并手动创建一个新实例。因此,从这个意义上说,它不是一个单例。