1

Sometimes singleton is actually needed and Node's caching system is not reliable. Even the official docs mentioned it:

Modules are cached based on their resolved filename. Since modules may resolve to a different filename based on the location of the calling module (loading from node_modules folders), it is not a guarantee that require('foo') will always return the exact same object, if it would resolve to different files.

Source: https://nodejs.org/api/modules.html#modules_module_caching_caveats


How do you create a Singleton without relying on Node's cache? Is it even possible?

captainskippah
  • 1,350
  • 8
  • 16
  • A "singleton" doesn't make much sense in JS context because you don't have classes. You can just create a single instance of some object and if there is no constructor for it, then you cannot generate a second one. Although you *could* copy it, which is where a singleton fails the second time over. I suggest just using factory methods/functions and have a pool of one object returned. – VLAZ Apr 25 '19 at 11:07
  • @VLAZ : I think you are missing ES6. It has classes. – Sreehari Apr 25 '19 at 11:09
  • @Sreehari it has syntactic sugar over the existing in ES5 constructor functions. It doesn't have "classes" per se. There is no encapsulation - you cannot declare a constructor to be private or protected. In fact, a private constructor is an entirely foreign concept in JS. Anything in an object would be either "public" or simply hidden from scope. This is already achievable via the modules (leveraging closures) and classes offer nothing over or different to that. If you want something that *doesn't* have a constructor, you cannot use the `class` keyword - that's just an object with methods. – VLAZ Apr 25 '19 at 11:16
  • @VLAZ The concept of a singleton is quite specific. And the statement that it doesn't make sense in JS... doesn't make sense. It's possible to provide singletons with modules, this is very common recipe. – Estus Flask Apr 25 '19 at 11:21
  • @estus you can make a function throw an error when used with `new` but that simply means it's never used with `new`, not that it has a "private" constructor. What you're left with is a factory function of `makeX` that instantiates `X` if not present or simply returns it...which is a factory function. Similarly, a module exposing `getInstance` is a factory method. If you do `x = (() => {name: "bob"})()` or equivalent, that's a *single instance* in existence but still not the OOP singleton. Besides, as I said you can easily do `Object.create(singleton)` which breaks down the concept. – VLAZ Apr 25 '19 at 11:52
  • @VLAZ I'm not sure why you insist on private constructor. Singleton is a pattern, not specific design. If you can achieve single class instance with a module then it can be considered a singleton. Here's a relevant example I posted recently, https://stackoverflow.com/a/55827719/3731501 . There's a class that has single instance. Class itself can be not exported and remain private but that's the point where a singleton becomes antipattern IMO. – Estus Flask Apr 25 '19 at 12:17

1 Answers1

1

You are missunderstanding the docs. It means that if your filestructure is:

 /foo.js
 /bar.js
 /sub/foo.js
 /sub/bar.js

then require("foo") inside of the bar.js files will import different modules (/foo.js and /sub/foo.js).

NodeJS' caching system is reliable.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • It's `require("foo")` and not `require("./foo")`. I believe the quote says about a hierarchy of node_modules. – Estus Flask Apr 25 '19 at 11:17
  • @estus yes tgat wouod be another example, but still, the OP is missunderstabding the paragraph. It is not about caching being unreliable – Jonas Wilms Apr 25 '19 at 12:15