intravenous
intravenous copied to clipboard
How about get by Function rather than key?
The Problem statement
If I want to retrieve an instance of MyCustomClass, I have to first register it with a key name. For that I will have to require this and all the other modules on startup. That means one file will have to require all the modules first and then initialize the application.
This seems in efficient and quite a headache to maintain that one file which contains all the required modules.
RATHER: How about requiring them in modules that actually need them instead
var Dep1 = require('./dep1');
var Dep2 = require('./dep2');
function MyCustomClass () {}
MyCustomClass.$inject = [Dep1, Dep2]; //Instead of using key name
So the main idea is to be able to query on the Class name rather than the key name. What do you think?
This seems like a very specific use case. It would be auto-registering singletons that don't have any dependencies themselves (e.g. Dep1
cannot have any dependencies that come from the container).
If that's what you want to do, I think it would make more sense if you would create a simple wrapper around require
that handles auto-registration based on filename. Make sure it also keeps working once you minify.
Why can't Dep1
have dependencies injected in the same way? My idea is not a specific use case, infact that is what is being practiced by - AngularDI
Okay, I guess it depends on how you set up the modules you require, of course! I do prefer the explicitness of the registration step though.
Hmm, how would you specify the lifetime of the modules, if you skip the registration step?
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. source
Which means that the module's lifetime is the basically equal to the lifetime of the app. So technically you don't really have control over it. But you have control over object instantiation which is a completely different process and that what your DI module is perfectly doing.
The design philosophy I am referring to makes you not want to load all the modules initially but instead load them as and when needed.
Your approach is great and works really well provided that module is already registered.
Say module A
needs B
. To be able to create an instance of A
I would need to create an instance of B
. So to use A
I need to register B
first - container.register('b',B)
, which is supposed to be done manually and then create an instance of A
using intravenous. In my mind I need to make sure that I do a require('../B')
before I ask for an instance of A, and there is not restriction where I should do this.
I hope you are getting my point here.
Yes, I get that :) Thanks for the details, still. I'm just not sure how you would make sure that B can be instantiated as a singleton, per-request or unique?
Exactly the way you were doing it earlier. Only difference is I don't pass the keyname (First Parameter). Neither do query on it.
Ok, if you can provide a pull request I'd be more than happy to merge it in.
Great! on it!
I was not able to get enough time to work on this pull request. My approach would be to use es6 Map.
@tusharmath what you are saying defeats the whole purpose of DI. Imagine you have 10's or more classes all depending on the Dep2 dependency and you have required Dep2 in all of them. Tomorrow if you decorate or extend your Dep2 with new Class you will have to go and change the require statement in all the 10 places (or more) and chances are very likely that you will miss it one or other class.