Robert J.
Robert J.

Reputation: 2701

Angular inject service programatically into function

I have a custom RxJs function that handles exceptions from http calls which looks like following (simplified)

export default function applicationRxJsExceptionHandler<U>(defaultOutputValue: U = null, defaultErrorMessage: string = 'Error occured, requested operation has not been executed', logToConsole: boolean = true) {
    return function <T>(source: Observable<T>) {
        return source.pipe(catchError((err: ProblemDetails | ValidationProblemDetails | any) => {
            if (err instanceof ValidationProblemDetails) {                   
                var errorDialogService = GlobalAppInjector.get(ValidationErrorDialogService);
                errorDialogService.ShowValidationErrorDialog(err).subscribe(_ => { });

            } else if (err instanceof ProblemDetails) {
                //... other code here
            }
            else {
                //.. other code here                   
            }

            if (logToConsole)
                console.log(err);

            return of(defaultOutputValue);
        }))
    }
}

As this default function does not have a constructor, which I could use to inject my ValidationErrorDialogService, and also I did not want to insert it as a separate parameter (as number of services can grow over time), I did the following:

in my app.component.ts I created a new global variable

export let GlobalAppInjector: Injector;

And then, within the same app.component, I injected Angular Injector in constructor and populated my global variable as following:

export let GlobalAppInjector: Injector;

@Component({
  selector: 'skeleton-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {

  constructor(private injector: Injector){
    GlobalAppInjector = this.injector;
  }
}

The reason why I went for this solution was, that I was unable to access already existing Injector directly from my custom function. What I don't like about this is, that I have just created a dependency in my app.component, only for the sole purpose of my custom function which seems like an overkill.

I am sure that there should be a better way how to do it. Any help in respect to this matter would be highly appreciated.

Upvotes: 2

Views: 713

Answers (1)

Anders
Anders

Reputation: 700

Instead of trying to register the Injector globally, I'd instead recommend that you take in the injector as an argument to your RxJs operator.

It's a much cleaner approach, and unit testeable.

Upvotes: 2

Related Questions