Giter Site home page Giter Site logo

Comments (14)

vojtajina avatar vojtajina commented on June 15, 2024

Yep, just do:

@Provide(Promise)
function getPromise () {
  return Promise;
}
@Inject(Promise)
class Deferred {
  constructor(Promise) {
    this.promise = new Promise();
  }
}

from di.js.

vojtajina avatar vojtajina commented on June 15, 2024

It is verbose, but this is not a common pattern. Do you have any other use cases?

from di.js.

vojtajina avatar vojtajina commented on June 15, 2024

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.

petebacondarwin avatar petebacondarwin commented on June 15, 2024

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.

petebacondarwin avatar petebacondarwin commented on June 15, 2024

Or this could be turned into some kind of annotation...

@ProvideValue
export class Promise { ... }
@ProvideValue('config')
export var config = { ... };

from di.js.

vojtajina avatar vojtajina commented on June 15, 2024

@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.

petebacondarwin avatar petebacondarwin commented on June 15, 2024

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.

vojtajina avatar vojtajina commented on June 15, 2024

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.

RGBboy avatar RGBboy commented on June 15, 2024

@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.

vojtajina avatar vojtajina commented on June 15, 2024

@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.

RGBboy avatar RGBboy commented on June 15, 2024

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.

OliverJAsh avatar OliverJAsh commented on June 15, 2024

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 requires and di.js injections. It would be nice if everything was injected using di.js.

from di.js.

dmtrs avatar dmtrs commented on June 15, 2024

@OliverJAsh Did you have any workaround on the above?

from di.js.

huan avatar huan commented on June 15, 2024

👍

from di.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.