41
votes

As you know it's possible to use Interceptors in new versions of Angular 4.

In mine, I want to cancel a request in interceptor in some conditions. So is it possible? or maybe what should I ask is, Which way I should do that?

Also It will be Ok! if I found a way to rewrite some response to the request instead of canceling it.

7
What do you mean by "rewrite some response"? It is easy to edit a request before handling it, if that's what you mean. - Jun Kang
The documentation has an example: angular.io/guide/http#caching - JB Nizet
I mentioned this because of some features in angularjs that I saw in stackoverflow.com/a/38926333/3534952. - Behnam Azimi
@JBNizet I reviewed the documentation over and over again! I think this one is not mentioned in documentation or maybe I can not see it! What I want I exactly is cancel a request or maybe rewrite another response instead of what will get from server. - Behnam Azimi
The documentation I linked to has the following comment: A cached response exists. Serve it instead of forwarding the request to the next handler. So it does return a cached response instead of actually sending the request to the server. - JB Nizet

7 Answers

65
votes

I think all you have to do to cut the interceptor chain is to simply return an empty Observable like so:

import { EMPTY } from 'rxjs';

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (stopThisRequest) {
    return EMPTY;
  }

  return next.handle(request);
}
10
votes

Inspired by @RVP answer I have found out that it's possible to cut the chain with an error in the same simple way using Observable.throw()

//...
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (stopThisRequestWithError) {
        return Observable.throw('Error message');
    } else {
        return next.handle(req);
    }
}

This avoids fulfilling response promises with undefined values.

6
votes

This is just a slight variant of RVP's answer

import { NEVER } from 'rxjs';

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (stopThisRequest) {
    return NEVER;
  }

  return next.handle(request);
}

I used NEVER instead of EMPTY to avoid dealing with undefined values in my subscriptions (or promises).

Use NEVER if you don't want your subscription callback to be invoked

1
votes

To Angular 6, you need can user the following structure to return a empty Observable:

import {Observable} from 'rxjs';
import {empty} from 'rxjs/internal/Observer';

//...

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (stopThisRequest) {
        return Observable.create(empty);
    } else {
        return next.handle(req);
    }
}
0
votes

@RVP's code will work, We can do one more thing for same.

add return only, it will also work

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
          if(helper.isTokenExpired(tokenVal)){
              return;
          }
        .
        . <{code}>
        .

    }
0
votes

As suggested above, there is more optimal way to handle the error with custom response

import { throwError, Observable } from 'rxjs';
import { HttpEvent } from '@angular/common/http';

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (authFailedDummy(request)) {
    return throwError(new Error('Authorization error: The request did not go through'));
  }
  return next.handle(request);
}
-8
votes
let sub = this.http.get(url, {headers: reqHeaders})
            .subscribe(
                (res) => {
                    res = res.json();
                }
            );

sub.unsubscribe();