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

i'm studying how nodejs module system works.
I've found so far this literature:
https://nodejs.org/api/modules.html
http://fredkschott.com/post/2014/06/require-and-the-module-system/
http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm
It helps me to understand a few points however is still have these questions:
If i have a expensive resource (let's say database pooling connection) inside a module, how can i make sure that by requiring the module again i am not re-evaluating the resource?
How can i dynamically unload a disposable resource once i already called the 'require' on it?
It's important because i have some scenarios that demands me to make sure that i have a single instance of database pool. because of this i'm exporting modules which are able to receive parameters instead of just require the expensive resource.
Any guidance is very appreciated.

Alon Salont has written an EXCELLENT guide to understanding exports in NodeJS (which is what you're accessing when you call require()) here:
http://bites.goodeggs.com/posts/export-this/#singleton
If you study the list of options for what a module can export, you'll see that the answer to your question depends on how the module is written. When you call require, NodeJS will look for the module loaded in its cache and return it if it already had it loaded elsewhere.
That means if you choose to export a Singleton pattern, are monkey-patching, or creating global objects (I recommend only the first one in your case), only ONE shared object will be created / will exist. Singleton patterns are good for things like database connections that you want to be shared by many modules. Although some argue that "injecting" these dependencies via a parent/caller is better, this is a philosophical view not shared by all, and singletons are widely used by software developers for shared-service tasks like this.
If you export a function, typically a constructor, require() will STILL return just one shared reference to that. However, in this case, the reference is to a function, not something the function returns. require() doesn't actually CALL the function for you, it just gives you a reference to it. To do any real work here, you must now call the function, and that means each module that requires this thing will have its own instance of whatever class the module provides. This pattern is the more traditional one where a class instance is desired / is the goal. Most NPM modules fit this category, although that doesn't mean a singleton is a bad idea in your case.

Related

In browsers + Node, what is the scope of a module?

I'm wondering what the scope of a module is in both browsers and Node. I'm specifically trying to understand whether a module-level variable is created once per app, or many times. Is a new instance of the module created on each import, or is it the exact same module shared across all imports? Many thanks!
There are several JS module flavours - ESM, CommonJS, AMD. Their common trait is that they are evaluated once on first import, at least under normal circumstances. Doing the opposite would make them inefficient for sharing data.
Exporting class instance is a common way to share one instance across the application without making a class a singleton.
The ways that can make a module be evaluated multiple times (intentionally or not) include having many copies of a module, different filename case on import in case-insensitive system, the modification of Node module cache.

Webpack: Is duplicate module loading inefficient?

From my understanding, webpack (and other similar bundlers) ensures that if the same module is required across multiple parts of the app:
That code will only be loaded once
Each time the same module is required, a new instance is created, rather than all sharing the same scope
Firstly, are my above assumptions correct? If so, is it bad optimisation to have multiple instances of the same module being created?
In my example I am creating an app that will be using ThreeJS. This is a rather large library. Many of the modules in my app will want to require this library.
Is it bad practice to keep on requiring a library like this? Or should I be passing a single instance from module to module instead of requiring multiple times?
I'd be interested to know if there are any common patterns for dealing with this, if it is indeed an issue.
This assumption:
Each time the same module is required, a new instance is created,
rather than all sharing the same scope
is wrong for two reasons:
Whether an instance is created or not, will depend on what is returned by the required module (it could return nothing).
Even if the module initialises an instance, only one will be created, as the code in the module is only run once.
With that said, requiring the same module multiple times should have no impact in performance.

Index-file to module-instance interaction

I am making a computer system which I have broken down into several smaller parts.
From a given experience, it is crucial in software development to keep systems small.
In order to do that I am implementing a module which serves a specific purpose, all and by itself without having any idea what the rest of the system is doing. (ideal)
So this module goes there and does its thing, and when an event occurs in an instance of this module, I want the index file to become aware of that happening.
I do not want this module to communicate directly to the other modules, as they should not communicate with each other, thereby decreasing dependencies within the system.
Now, I have made the instance and the instance does everything right,
but when an event occurs in this instance, how do I get that information over to the index file?
An event of this instance is implemented in the following manner:
the_div.addEventListener('mousedown',this.react_to_mouse_down_function);
And here its a question how its best to get this happening to the index file, I can do in the index file:
the_div.addEventListener('click', the_function);
but that forces the index file to be aware of things going on in the instance because
the instance has children which each has event detector and their numbers can grow and shrink and god knows what.
It would be best if the index file wouldn't need to understand how the instance of the module works, and thereby not needing to be generating new event listeners on the fly as the instance is living.
How is it best to setup the interaction between the index file and this instance?
This sounds like a pub/sub problem. This would let the module publish a specific custom event when state changes and the index (or any other module) can subscribe to that event if needed. The module does not communicate with anything besides the pub/sub controller.
Here is a good link:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript
I find myself referring to various sections of this page often.
The solution I came to was to have a designated module called 'messages', and it takes care of receiving event driving messages from instances.
An instance of the message module is made global and named 'imessages'. And each module, when an event within it occurs, checks if it has access to the global 'imessage' object, and if it does and the imessage object contains a function with the same name as the given event, it calls that function and sends relevant information as arguments.
The given message function is now defined in the index file in a designated message module, relieving this module of any further interaction with the outside world.
Modules with this functionality need now not communicate with any other concrete modules. Just the index file.
It just needs to be stated in the API of each module applying this, how this dependency decreasing functionality of it works.

Is the use of the mediator pattern recommend?

I am currently reading http://addyosmani.com/resources/essentialjsdesignpatterns/book/#mediatorpatternjavascript
I understand the mediator pattern as some sort of object which sets up publish and subscribe functionality.
Usually I am setting up objects which already provide subscribe(), publish() methods. Concrete Objects extend this base object so that subscribe() and publish() are always registered as prototype attributes.
As I understand right the mediator pattern is used to add the publish-subscribe-methods to an object.
What is the benefit of this practice? Isn't it a better practice to provide a base object with publish and subscribe functions than letting a mediator set up at construction?
Or have I understood the mediator pattern wrong?
As what I have learned from similar posts some time ago:
The mediator pattern provides a standard API for modules to use.
Let's have an example:
Your app's thousands of modules heavily rely on jQuery's $.post. If suddenly, your company had licensing issues and decided to move over to, for example, MooTools or YUI, would your look for all the code that uses $.post and replace them with something like MooTools.post?
The mediator pattern solves this crisis by normalizing the API. What the modules know is that your mediator has a post function that can do AJAX post regardless of what library was used.
//module only sees MyMediator.post and only knows that it does an AJAX post
//How it's implemented and what library is used is not the module's concern
jQuery.post -> MyMediator.post -> module
MooTools.post -> MyMediator.post -> module
YUI.post -> MyMediator.post -> module
The mediator serves as the "middle-man" for intermodule communication.
One problem in newbie JS development is when modules are interdependent. That is when:
MyClassA.something = MyClassB.method();
MyClassB.something = MyClassA.method();
But what if something is wrong in MyClassB and the developer took it out of the build. Would you look for and strip out all code in MyClassA that uses MyClassB so that it does not break due to the absence of MyClassB?
The mediator pattern's publish and subscribe pattern solves this by making the module subscribe to an event instead of directly interfacing with the other modules. The mediator acts as a collection of callbacks/subscriptions that are fired when events are published.
This "anonymous" subscribing results in partial loose-coupling. Modules would still need to know which modules to listen to or at least a set of events to listen to, but they are connected in a way that won't result in breakage if any one of them is taken out. All they know is that they subscribed to the event and will execute when that event happens - regardless of who fires it, if it fires at all, or if the trigger exists.
You can achieve mediation without using eventing (pub/sub).
In complex/sophisticated flows, it can be challenging to debug or reason about code that is purely event driven.
For an example on how you can create a mediator without pub/sub, you can take a look at my project jQueryMediator:
https://github.com/jasonmcaffee/jQueryMediator

requireJS : How to structure Javascript for an entire site?

I have 3000+ lines of javascript that I need to get into a sensible/maintainable structure. I have chosen to use requireJS as it has been recommend to me by a few people. I have a bunch of variables that are used throughout the application and need to be available everywhere. I also have a bunch of functions that need to be available everywhere. Apart from these two dependencies most of the code can be divided off into their own modules.
I am having trouble understanding how to manage my main variables so that if one module of code makes changes to the variables the rest of the JS modules will see that change. I think I need to see a few examples that demonstrate how requireJS is intended to work on a larger scale that the examples in the documentation.
If anyone is an experienced requireJS user I would love the hear your tips!
The whole point of RequireJS is to avoid the need for these global variables and global functions.
Can't you wrap those globals into a module, then depend on it in your other modules?
For example, a RequireJS modularized Dojo may be something like:
dojo/cache module
dojo/string module (requires dojo/cache)
dojo/date module (requires dojo/string)
dojo/cookie module (requires dojo/string)
:
:
dojo module (requires everything above, make them all into sub-objects, say, e.g. dojo.cache, dojo.string, dojo.date etc.)
user module #1 (requires dojo)
user module #2 (maybe only requiring dojo/string)
RequireJS gives you better options for encapsulating modules, but it doesn't change Javascript itself at all. As a transition strategy, you can still define your globals inside the function block. Depending on the module that contains these definitions will ensure that it has run before the dependent modules.
Next step would be to assign those methods to an object other than window, and then use that object through the variable received from RequireJS module dependency.
Hopefully by the time you've done this, you might have some insight into a cleaner solution. I refactored (and still am) a single-file project into several files, including optional plug-ins, although I did most of it before adding RequireJS to the mix.
See the RequireJS documentation:
Defining a module
Definition Functions with Dependencies
If the module has dependencies, the first argument should be an array of dependency names, and the second argument should be a definition function. ... The dependencies will be passed to the definition function as function arguments
define(["./cart", "./inventory"], function(cart, inventory) {
// ...
return { ... };
}
);
So I think you can define() your main module like all other modules and make the submodules depend on that main module. Then the module object is passed as an argument to the definition function of a submodule. You don't have to use global variables.
If you want to share information between modules, attach the information to the module object, and have the other modules rely on that module, and check its property.
If you have existing code, you can assign to window.x to provide a global x while you are cleaning it up.

Categories

Resources