避免重新评估和动态卸载使用 `require` 调用的对象

Avoiding re-evaluation and dynamically unloading objects called with `require`

我正在研究 nodejs 模块系统的工作原理。

到目前为止我发现了这篇文献:

  1. https://nodejs.org/api/modules.html
  2. http://fredkschott.com/post/2014/06/require-and-the-module-system/
  3. http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm

它帮助我理解了几点但是仍然有这些问题:

这很重要,因为我有一些场景要求我确保我有一个数据库池实例。因此,我正在导出能够接收参数的模块,而不仅仅是需要昂贵的资源。

非常感谢任何指导。

Alon Salont 在 NodeJS 中编写了一篇理解 exports 的优秀指南(调用 require() 时访问的内容): http://bites.goodeggs.com/posts/export-this/#singleton

如果您研究模块可以导出的选项列表,您会发现问题的答案取决于模块的编写方式。当您调用 require 时,NodeJS 将查找在其缓存中加载的模块,如果它已在其他地方加载,则 return 查找它。

这意味着如果您选择导出单例模式、进行猴子修补或创建全局对象(我建议您只使用第一个),则只会创建/存在一个共享对象。单例模式适用于您希望由多个模块共享的数据库连接之类的事情。尽管有人认为 "injecting" 通过 parent/caller 这些依赖关系更好,但这是一个并非所有人都认同的哲学观点,并且软件开发人员广泛使用单例来完成这样的共享服务任务。

如果您导出一个函数,通常是一个构造函数,require() 仍然 return 只是一个共享引用。但是,在这种情况下,引用是一个函数,而不是函数 returns。 require() 实际上并没有为你调用函数,它只是给你一个引用。要在这里做任何真正的工作,您现在必须调用该函数,这意味着 requires 这个东西的每个模块都将有自己的 class 模块提供的任何实例。这种模式是更传统的模式,其中 class 实例是需要的/是目标。大多数 NPM 模块都属于此类,尽管这并不意味着单例在您的情况下是个坏主意。