2

Is there a way to use angular's http interceptors to intercept the response, and kinda delete it / throw it away, so that future downstream callbacks aren't executed?

I want it to behave such that neither of the console.log's are executed.

this.http.get('/foo').subscribe(
    data => console.log("success", data),
    err => console.log("fail.", err)
);

I've seen examples that modify the response, or replace the response with null or some other sentinel value, but I'd rather not do that because then all of my success/fail handlers must look for the sentinel, which reduces the usefulness of using an interceptor for handling certain responses.

I have a feeling this is more of an rxjs question and less of an angular interceptor question, but I'm just not familiar enough with rx yet to be sure.

If it matters, I'm using angular 5.1

goat
  • 31,486
  • 7
  • 73
  • 96
  • 1
    The description of interceptor is "Intercepts `HttpRequest` and handles them.". I'm not sure if it's possible to use HttpInterceptor to intercept response. – Harry Ninh Feb 14 '18 at 22:45
  • @HarryNinh it's possible - note I said "I've seen examples that modify the response" – goat Feb 14 '18 at 23:59
  • Will putting something like `return next.handle(req).switchMap(() => Observable.empty());` in the interceptor do for you? – Harry Ninh Feb 15 '18 at 02:43
  • Hi @goat, maybe this will help you: https://stackoverflow.com/questions/45566944/angular-4-3-httpclient-intercept-response – Narm Feb 15 '18 at 03:21
  • @HarryNinh thanks, that worked :) if you post it as an answer I'll accept it since it answered the question I asked. Unforntunately, to keep it simple, I didn't include the fact that I'm using `get(...).toPromise().then(...)` instead of `subscribe(...)`, and it seems `toPromise` changes the behavior and will cause the promise to resolve with an undefined argument. Any ideas how to get around that (eg, so it doesn't resolve)? Maybe I should ask this as a new question. – goat Feb 16 '18 at 20:12

2 Answers2

1

You can use Observable.empty to complete the stream without emitting any data. To combine it with HttpInterceptor, chain it to next.handle:

return next.handle(req).switchMap(() => Observable.empty());

I don't know how to do that with Promise, sorry.

Harry Ninh
  • 16,288
  • 5
  • 60
  • 54
0

I found another method that will prevent subscribe() callbacks from being called. Here's an example interceptor that will refrain from calling downstream subscribers if a certain http header is present in the HttpResponse.

Be warned though, that this method doesn't really "throw the response away". Instead, it indefinitely delays the response. If you have code that uses timers (eg, some code that will error if a neither a success nor error response is received within 60 seconds), it could be a problem, because that's exactly how this method works - it just never responds.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
        switchMap((event: HttpEvent<any>) => {

            // In this example, I only care about checking valid http responses.
            // But, if you also want to inspect errors, you might consider checking for HttpResponseBase or HttpErrorResponse
            if (event instanceof HttpResponse) {

                // Check if this response has a certain http response header set.
                // If so, we throw the response away.
                if (event.headers.has('my-custom-header')) {
                    // We intentionally return an Observable that will never complete. This way,
                    // downstream subscribers will never receive anything, and any .toPromise()
                    // conversions that may be present will also never be invoked because toPromise() only
                    // gets invoked when the Observable completes.
                    // It doesn't actually throw the response away, but rather, it makes the subscribers wait forever, so they will never get a response.
                    // Be careful if you use timeouts.
                    return new Subject<HttpEvent<any>>();
                }

            }

            // The default case - we pass the response back through unmodified.
            return Observable.of(event);
        })
    );
}

// These console.logs will not be called
this.http.get('/foo').subscribe(
    data => console.log("success", data),
    err => console.log("fail.", err)
);

// Neither will these
this.http.get('/foo').toPromise(
    data => console.log("success", data),
    err => console.log("fail.", err)
);
goat
  • 31,486
  • 7
  • 73
  • 96