Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

How to cancel/abort all pending HTTP requests in angular 4+.

There is an unsubscribe method to cancel HTTP Requests but how to cancel all pending requests all at once.

Especially while route change.

There is one thing I did

ngOnDestroy() {   this.subscription.unsubscribe(); } 

but how to achieve this globally

Any Ideas?

like image 755
Sibiraj Avatar asked Sep 06 '17 07:09

Sibiraj


2 Answers

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 :

  • Avoiding take until leaks

  • A great answer from seangwright

like image 117
Alexis Facques Avatar answered Oct 21 '22 14:10

Alexis Facques


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 { } 
like image 45
Bladito Avatar answered Oct 21 '22 16:10

Bladito