Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject http interceptor at component

I've created this http interceptor:

@Injectable()
export class NoopInterceptor  implements HttpInterceptor {
    public my_status: boolean = true;
    private _statusChange: Subject<boolean> = new Subject<boolean>();
    public statusChange$ = this._statusChange.asObservable();
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.changeStatus(false);
        const my_req = req.clone({
            url: API_PATH + req.url
        });
        return next
            .handle(my_req)
            .do(event => {
                if (event instanceof HttpResponse)
                    this.changeStatus(true);
            });
    }

    private changeStatus(status: boolean) {
        this.my_status = status;
        this._statusChange.next(this.my_status);
    }
}

And in my component, I did it:

export class AppComponent implements OnInit {
    public my_status: boolean;
    constructor(private httpInterceptor: NoopInterceptor) {
        this.my_status = httpInterceptor.my_status;
        httpInterceptor.statusChange$.subscribe(this.changeStatus);
    }

    changeStatus(status: boolean) {
        this.my_status = status;
    }

}

At app.module, I provided the interceptor like this:

providers: [
   {
        provide: HTTP_INTERCEPTORS,
        useClass: NoopInterceptor,
        multi: true
    }
]

When I do in the way above, I get No provider for NoopInterceptor!, because I'm not providing NoopInterceptor, but if I provide NoopInterceptor like this:

providers: [
   {
        provide: HTTP_INTERCEPTORS,
        useClass: NoopInterceptor,
        multi: true
    },
    NoopInterceptor
]

I'll get two injections and the component will get the wrong one, then I won't be able to subscribe statusChange. How can I workaround this?

like image 567
João Paulo Avatar asked Dec 05 '22 13:12

João Paulo


2 Answers

It's likely possible to create single interceptor instance with:

providers: [
    NoopInterceptor,
   {
        provide: HTTP_INTERCEPTORS,
        useExisting: NoopInterceptor,
        multi: true
    }
]

But a proper solution for loading indicator state (I guess statusChange serves for this purpose) is to detach it from an interceptor and make it a separate provider.

And as it's shown here, there should be request counter because there can be simultaneous requests, and it should be affected by both success and error do callbacks.

like image 177
Estus Flask Avatar answered Jan 02 '23 10:01

Estus Flask


Have you tried to put NoopInterceptor before the provide of HTTP_INTERCEPTOR and useExisting instead of useClass ? In that way you should get only one NoopInterceptor instance.

like image 31
Juli3n Avatar answered Jan 02 '23 11:01

Juli3n