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?
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
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 love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With