Singleton pattern in nodejs - is it needed?


Question

I recently came across this article on how to write a singleton in Node.js. I know the documentation of require states that:

Modules are cached after the first time they are loaded. Multiple calls to require('foo') may not cause the module code to be executed multiple times.

So it seems that every required module can be easily used as a singleton without the singleton boilerplate-code.

Question:

Does the above article provide a round about solution to creating a singleton?

1
83
8/23/2018 12:51:14 PM

Accepted Answer

This has basically to do with nodejs caching. Plain and simple.

https://nodejs.org/api/modules.html#modules_caching

(v 6.3.1)

Caching

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.

Multiple calls to require('foo') may not cause the module code to be executed multiple times. This is an important feature. With it, "partially done" objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.

If you want to have a module execute code multiple times, then export a function, and call that function.

Module Caching Caveats

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.

Additionally, on case-insensitive file systems or operating systems, different resolved filenames can point to the same file, but the cache will still treat them as different modules and will reload the file multiple times. For example, require('./foo') and require('./FOO') return two different objects, irrespective of whether or not ./foo and ./FOO are the same file.

So in simple terms.

If you want a Singleton; export an object.

If you do not want a Singleton; export a function (and do stuff/return stuff/whatever in that function).

To be VERY clear, if you do this properly it should work, look at https://stackoverflow.com/a/33746703/1137669 (Allen Luce's answer). It explains in code what happens when caching fails due to differently resolved filenames. But if you ALWAYS resolve to the same filename it should work.

38
9/6/2018 11:26:37 AM

All of the above is overcomplicated. There is a school of thought which says design patterns are showing deficiencies of actual language.

Languages with prototype-based OOP (classless) do not need a singleton pattern at all. You simply create a single(ton) object on the fly and then use it.

As for modules in node, yes, by default they are cached, but it can be tweaked for example if you want hot-loading of module changes.

But yes, if you want to use shared object all over, putting it in a module exports is fine. Just do not complicate it with "singleton pattern", no need for it in JavaScript.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon