Comments (14)
Yep, just do:
@Provide(Promise)
function getPromise () {
return Promise;
}
@Inject(Promise)
class Deferred {
constructor(Promise) {
this.promise = new Promise();
}
}
from di.js.
It is verbose, but this is not a common pattern. Do you have any other use cases?
from di.js.
I'm thinking, we might provide some helper for defining "values":
// when somebody asks for "Promise", give him the value of Promise (do not instantiate it)
var m1 = bind(Promise).toValue(Promise);
var c = bind('config').toValue({crashOnStart: true, ignoreAllErrors: false});
var injector = new Injector([m1, c]);
from di.js.
Since the third parameter to an injector is a map of providers, where at the moment each "Provider" must be an object of the form,
{ provider: ..., params: ..., create: ... }
I was playing with the idea of a helper along the lines of:
class ValueProvider {
constructor(value, isPromise = false) {
this.provider = value;
this.params = [];
this.isPromise = isPromise;
}
create(args) {
return this.provider;
}
}
and then you could do...
var providers = new Map;
providers.set(Promise, new ValueProvider(Promise));
var injector = new Injector([modules], null, providers);
from di.js.
Or this could be turned into some kind of annotation...
@ProvideValue
export class Promise { ... }
@ProvideValue('config')
export var config = { ... };
from di.js.
@petebacondarwin @ProvideValue
annotation would only work with functions (annotation is just setting a .annotations
property and setting this property on an object is dangerous IMHO as your object would suddenly get the annotations
property overriden).
The third argument to the constructor is kind of internal thing, I would rather not have people using that.
... some stream of consciousness... probably do not read this...
I need to think about this some more... maybe @ProvideValue
is a good idea and it will be fine with objects... but I'm still thinking that the whole @Provide
thing is wrong and we should rather go bind(x).to(y)
way as that creates a new "binding" object rather than adding a property on the provider. The problem is that annotations are attached to the provider... let's say you have a single class (a provider) LocalStorageCache
that should be bound to multiple tokens (say TemplateCache
, and UsersCache
)... with annotations there is no way to do that (except creating another LocalStorageForUsers
that inherits from LocalStorageCache
)... basically it is all right to append information about what the provider needs (@Inject
, @InjectLazy
, @InjectPromise
) as that will never change for given provider.... but the information of what token it provides... is something that should probably not be tight to the provider... the same probably applies to scope annotations...
So right now, I'm thinking bind(x).to(y)
would be a syntactic sugar to create a Provider
(something that injector creates internally - for each provider, it parses the annotations and create either ClassProvider
or FactoryProvider
). and thus it would override the annotations on the provider.
from di.js.
Regarding this value thing: In @jeffbcross's case I think that what he really needs is for the requester of the service to be able to decide whether or not to get the class or the instance. In most cases you might like to get the instance but there are a smaller number of cases where, when testing for instance, you might like the actual class.
Is this not what the @InjectLazy
annotation is supposed to support? Or if not, perhaps something similar could be implemented?
@Provide(Promise)
class Promise { ... }
@InjectLazy(Promise)
class Deferred {
constructor(createPromise) {
this.promise = createPromise();
}
}
from di.js.
You could use @LazyInject
for this, but it's not as pretty either, you would have to annotate the Promise
, so that you can pass it the "resolver" argument. Something like this:
annotate(Promise, new Inject('resolver'));
@InjectLazy(Promise)
class Deferred {
constructor(createPromise) {
this.promise = createPromise('resolver', function(resolve, reject) {});
}
}
So I think this use case is really, you are asking for the class, in which case I don't think having a simple wrapper factory is that big of deal. You do this once per project.
I was also thinking, maybe we could support "default providers" for non-annotated stuff. Default provider is basically taking the token and instantiating. I'm suggesting, if the token (default provider) is not annotated with @Inject
, we take it as a direct value. Then, you could do just:
@Inject(Promise)
class Deferred {
constructor(Promise) {
this.p = new Promise(function(resolve, reject) {});
}
}
This would be also very convenient in Node, where you could use it to inject all the stuff that does not expect to be instantiated (such as most of the core modules). For instance:
var fs = require('fs');
@Inject(fs.writeFile)
class DocWriter {
constructor(writeFile) {
// ...
}
And mock it out in the test:
use(function fakeWrite() {}).as(fs.writeFile);
The only thing I'm worrying is that if you forget to put @Inject
it will suddenly behave differently - injecting the class/function directly, rather then calling it... What do you think?
from di.js.
@vojtajina I have been thinking of the same solution.
+1 for injecting just the value for tokens that are not annotated.
For some of the modules I have been writing I have had to wrap other non di annotated modules just to get them into the di paradigm. I have only wrapped a few and can see this becoming quite an overhead as I use more external libraries. This would make what I am working on much quicker, easier and cleaner.
from di.js.
@RGBboy you can give it a try, it's implemented in https://github.com/angular/di.js/tree/non-annotated-tokens-inject-as-values
The only problem with this approach is that now you have to put @Inject
on every provider, even if it does not accept any argument.
from di.js.
I just got round to trying this out. I like the change. I don't mind having to put the Inject annotation on a provider. I think it makes code more clear as to what it is trying to achieve. Are there any other downsides to this approach?
from di.js.
This would be also very convenient in Node, where you could use it to inject all the stuff that does not expect to be instantiated (such as most of the core modules).
Yes, it would. I'm using di.js in production on a large app and I'm having to create a wrapper factory for every Node module I need to be able to mock in my tests.
My app is currently a cocktail of simple Node require
s and di.js injections. It would be nice if everything was injected using di.js.
from di.js.
@OliverJAsh Did you have any workaround on the above?
from di.js.
👍
from di.js.
Related Issues (20)
- Mock providers not cached HOT 3
- Document TransientScope HOT 2
- annotate helper and SuperConstructor doesn't work HOT 1
- Using di2 in ES6 project with Traceur HOT 1
- Chrome Extension
- Non-module constructor parameter HOT 1
- InjectPromise HOT 8
- Invalid assumption of a class to be a factory
- minification issues HOT 13
- Exception: Constructors of derived class must contain a super call when the memberVariables option is enabled HOT 1
- How to inject literal values (like strings)? HOT 8
- example how to use it with typescript HOT 3
- DI.js dead? HOT 3
- Using angular/di.js in a babel runtime gives error HOT 23
- What about reusable classes? HOT 2
- import real module when writing a mock sounds ugly HOT 2
- Question: interfaces
- Alive? HOT 10
- Meet - refactoring di.js to TypeScript version - `ts-di` =) HOT 1
- node main.js Error
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from di.js.