How to cancel/unsubscribe all pending HTTP requests in Angular 4+ How to cancel/unsubscribe all pending HTTP requests in Angular 4+ angular angular

How to cancel/unsubscribe all pending HTTP requests in Angular 4+


Checkout the takeUntil() operator from RxJS to globally drop your subscriptions :

- RxJS 6+ (using the pipe syntax)

import { takeUntil } from 'rxjs/operators';export class YourComponent {   protected ngUnsubscribe: Subject<void> = new Subject<void>();   [...]   public httpGet(): void {      this.http.get()          .pipe( takeUntil(this.ngUnsubscribe) )          .subscribe( (data) => { ... });   }   public ngOnDestroy(): void {       // This aborts all HTTP requests.       this.ngUnsubscribe.next();       // This completes the subject properlly.       this.ngUnsubscribe.complete();   }}

- RxJS < 6

import 'rxjs/add/operator/takeUntil'export class YourComponent {   protected ngUnsubscribe: Subject<void> = new Subject<void>();   [...]   public httpGet(): void {      this.http.get()         .takeUntil(this.ngUnsubscribe)         .subscribe( (data) => { ... })   }   public ngOnDestroy(): void {       this.ngUnsubscribe.next();       this.ngUnsubscribe.complete();   }}

You can basically emit an event on your unsubscribe Subject using next() everytime you want to complete a bunch of streams. It is also good practice to unsubscribe to active Observables as the component is destroyed, to avoid memory leaks.

Worth reading :


You can create an interceptor to apply takeUntil operator to every request. Then on route change you will emit event that will cancel all pending requests.

@Injectable()export class HttpCancelInterceptor implements HttpInterceptor {  constructor(private httpCancelService: HttpCancelService) { }  intercept<T>(req: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {    return next.handle(req).pipe(takeUntil(this.httpCancelService.onCancelPendingRequests()))  }}

Helper service.

@Injectable()export class HttpCancelService {  private cancelPendingRequests$ = new Subject<void>()  constructor() { }  /** Cancels all pending Http requests. */  public cancelPendingRequests() {    this.cancelPendingRequests$.next()  }  public onCancelPendingRequests() {    return this.cancelPendingRequests$.asObservable()  }}

Hook on route changes somewhere in your app (e.g. onInit in appComponent).

this.router.events.subscribe(event => {  if (event instanceof ActivationEnd) {    this.httpCancelService.cancelPendingRequests()  }})

And last but not least, register the interceptor to your app.module.ts:

  import { HttpCancelInterceptor } from 'path/to/http-cancel.interceptor';  import { HTTP_INTERCEPTORS } from '@angular/common/http';  @NgModule({    [...]    providers: [      {        multi: true,        provide: HTTP_INTERCEPTORS,        useClass: HttpCancelInterceptor      }    ],    [...]  })  export class AppModule { }


If you don't want to manually unsubscribe all subscriptions, then you can do this:

export function AutoUnsubscribe(constructor) {  const original = constructor.prototype.ngOnDestroy;  constructor.prototype.ngOnDestroy = function() {    for (const prop in this) {      if (prop) {        const property = this[prop];        if (property && (typeof property.unsubscribe === 'function')) {          property.unsubscribe();        }      }    }    if (original && typeof original === 'function') {      original.apply(this, arguments)    };  };}

Then you can use it as decorator in your component

@AutoUnsubscribeexport class YourComponent  {}

but you still need to store subscriptions as component properties.And when you navigating out of component, AutoUnsubscribe function will occurs.