1

I have inherited an angular project where java style entity instances are mimicked using plain javascript objects.

This is how fake injection is implemented:

export class MyEntity {

  private http: Http;
  private someObservable: Observable<any>;

  init(dependencies, ...) {
    this.http = dependencies.http;
    this.someObservable = dependencies.someObservable;

    this.someObservable.subscribe((res) => { ...unimportant logic... });
  }
}

then in DI enabled code:

entity = new MyEntity();
entity.init({ http: this.http, someObservable: this.someObservable, ... }, ...);

My questions:

  1. Can http "malfunction" like this? I'm worried that it might not work fully (CD, interceptors or events might not trigger. etc). Right now it does not show any issues, but might be the code just wasn't tested well enough.

  2. Is there any way to release subscriptions created here conveniently? Normally i'd take care of that in an onDestroy hook, but that isn't available for plain classes. Some of the observables here are continuous, won't complete after first emit.

Refactor would take quite some time, so if there is a safe solution that might be preferable even if it's relatively ugly.

bitwise
  • 170
  • 12

2 Answers2

2

1) In my own project I have a ServiceHelper class which has http : HttpClient as an argument which is invoked from an @Injectable class and it works perfectly. Simplified example:

export class ServiceHelperCrl<T> {
  constructor(private http: HttpClient) {
  }

  get(id: number): Observable<T> {
    return this.http.get<T>('/some/rest/resource/path'+`/${id}`);
  }
}

2) I don't know why there is an Observable passed as an argument in your example or which subscriptions need to be released.

a) At the end of the day a simple solution could be to implement your custom onDestroy() method in that Java-Style-class and invoke it from your managed class which implements OnDestroy. There is an unsubscription example here: Angular/RxJs When should I unsubscribe from `Subscription` .

b) or you convert your java-style-class to an @Injectable class (but maybe that effort is bigger)

michaeak
  • 1,548
  • 1
  • 12
  • 23
  • Thanks! Regarding 2. it receives an emit from that observable when certain data needs to be synced online and then it does the necessary api calls. Anyway, it seems i can get away with refactoring only the subscriptions. – bitwise Feb 13 '20 at 16:09
  • @bitwise You are welcome! In which way are you refactoring the subscriptions? – michaeak Feb 14 '20 at 08:31
  • I changed them to BehaviorSubjects and access its value only. Luckily i could avoid having to trigger code on new emission. – bitwise Apr 17 '20 at 12:34
0

Finally i solved it like this, a static class that gets a reference to the Injector during app module init:

export class GlobalInjector {
    static injector: Injector;
}

... and in app.module or wherever it's soon enough:

export class AppModule {
  constructor (private injector: Injector) {
    GlobalInjector.injector = injector;
  }
}

can be used like this in a plain class (MyService is an injectable service class):

myDependency = GlobalInjector.injector.get(MyService);

For removing the subscription i found no good solution yet that doesn't need manual destroy calls.

bitwise
  • 170
  • 12