Angular 12 How to Cancel HTTP Calls on Router Change

Angular Interceptors play an important role to control and manipulate HTTP calls behavior which we do to get remote data from the server.

In this tutorial, we will get to know how to cancel unnecessary HTTP get, post or any request to server after a user route to another component in an application using Angular Interceptor services.

Angular application is created using multiple components each having different roles and data to display. In normal practice, we load data on the component’s onInit method. Suppose we have three components like StudentsList, TeachersList and ParentsList, so when a user navigates through these they will send an HTTP call to fetch data from the server. Meanwhile, the user switches the route from StudentsList to TeachersList, in this case, there are two calls in a stack with pending state and StudentsList data is no longer required as the user already switched to see TeachersList.

In such a case on frequent navigation over different routes leaves HTTP calls in a pending stack to get completed which are no longer required.

Using Interceptors and RxJS we can cancel these Now Not Required calls after user routes to new component view.

Let’s do it…

Step 1) Create HttpCancelService service

The HttpCancelService service will use A Subject which acts as an Observer to Observables.

Replace below code in httpcancel.service.ts file:

// httpcancel.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class HttpCancelService {

    private pendingHTTPRequests$ = new Subject<void>();

  constructor() { }

  // Cancel Pending HTTP calls
  public cancelPendingRequests() {
    this.pendingHTTPRequests$.next();
  }

  public onCancelPendingRequests() {
    return this.pendingHTTPRequests$.asObservable();
  }

}

Step 2) Create ManageHttpInterceptor Interceptor

Next, to keep an eye on HTTP calls and Router navigation, we will create an Angular Interceptor. This will also import the Service we created in the previous step.

Replace below code in managehttp.interceptor.ts file as shown below:

// managehttp.interceptor.ts
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { Router, ActivationEnd } from '@angular/router';
import { HttpCancelService } from '../services/global/httpcancel.service';
import { takeUntil } from 'rxjs/operators';

@Injectable()
export class ManageHttpInterceptor implements HttpInterceptor {

    constructor(router: Router,
        private httpCancelService: HttpCancelService) {
            router.events.subscribe(event => {
                // An event triggered at the end of the activation part of the Resolve phase of routing.
                if (event instanceof ActivationEnd) {
                  // Cancel pending calls
                  this.httpCancelService.cancelPendingRequests();
                }
            });
    }

    intercept<T>(req: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {
      return next.handle(req).pipe(takeUntil(this.httpCancelService.onCancelPendingRequests()))
    }
}

Step 3) Import Service and Interceptor in App Module

To provide our service and interceptor to project, we will import and add them in providers array in the app.module.ts file as shown below:

// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { HttpCancelService } from './services/httpcancel.service';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ManageHttpInterceptor } from './interceptors/managehttp.interceptor';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [
    HttpCancelService,
    { provide: HTTP_INTERCEPTORS, useClass: ManageHttpInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

That’s it now you will see previous HTTP calls getting canceled after user routes to a new URL.

2 thoughts on “Angular 12 How to Cancel HTTP Calls on Router Change”

  1. Looks good, but when all requests are cancelled, some pages, it shows empty. Do you know how to avoid it?

Leave a Reply to Cascudo Cancel Reply

Your email address will not be published. Required fields are marked *