5

Is it possible to call function in a Component from HttpInterceptor ?

@Injectable()
export class HttpResponseInterceptor implements HttpInterceptor {

  // constructor(@Inject(DOCUMENT) private document: any) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('HttpRequest<any> called');
    const started = Date.now();
    // Call component function
    return next.handle(req).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
        // Call component function on response
      }
    });
  }

}
Lansana Camara
  • 9,497
  • 11
  • 47
  • 87
Tushar
  • 53
  • 1
  • 4

1 Answers1

5

You should not call a component method from a service; this is not a good practice. If you wanted to do this, you'd have to basically pass the class instance of that component into the service, and it must have publicly accessible properties. But that is a dirty approach and you should avoid it.

You can, however, add to an observable stream from a service, and a component can subscribe to that observable stream and call whatever function it wants. That would be "the Angular way" of doing this.

With this approach, you can get the same piece of data in as many components as you want, and you can call as many functions as you want in those components. All you need to do is call subscribe() and voila.

For instance:

@Injectable()
export class HttpResponseInterceptor {
    dataStream: ReplaySubject<any> = new ReplaySubject();

    dataStream$(): Observable<any> {
        return this.dataStream().asObservable();
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        console.log('HttpRequest<any> called');
        const started = Date.now();

        return next.handle(req).do((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
                // Pass in some data in the `next()` function. 
                // Every time this is called, your components subscription function will be triggered.
                this.dataStream.next(...);
            }
        });
    }
}

@Component({...})
export class MyComponent {
    ngOnInit() {
        this.httpInterceptorService.dataStream$().subscribe(data => {
            // This will be triggered every time data is added to the stream in your HttpInterceptorService class.
            // Call your custom function here...
        });
    }
}
Lansana Camara
  • 9,497
  • 11
  • 47
  • 87
  • As an extension to this, this question + answer could be usefull: https://stackoverflow.com/questions/36261829/angular-2-component-listen-to-change-in-service – Patrick P Apr 26 '18 at 08:02
  • Mine Worked with BehaviourSubject instead of ReplaySubject – Pravinraj Venkatachalam Jul 09 '20 at 12:02
  • @PravinrajVenkatachalam `BehaviorSubject` also works fine. It just depends on whether or not you want the stream to emit all previous states to a new subscriber, and `ReplaySubject` does that. `BehaviorSubject` only emits the most recent value or the initial value to new subscribers. – Lansana Camara Jul 10 '20 at 16:26