How to cancel a HTTPRequest in Angular 2?
Asked Answered
E

6

91

How to cancel a HTTPRequest in Angular 2?

I know how to reject the request promise only.

return new Promise((resolve, reject) => {
    this.currentLoading.set(url, {resolve, reject});

    this.http.get(url, {headers: reqHeaders})
        .subscribe(
            (res) => {
                res = res.json();

                this.currentLoading.delete(url);
                this.cache.set(url, res);

                resolve(res);
            }
        );
});
Eipper answered 8/4, 2016 at 3:19 Comment(0)
O
90

You can call unsubscribe

let sub = this.http.get(url, {headers: reqHeaders})
            .subscribe(
                (res) => {
                    res = res.json();

                    this.currentLoading.delete(url);
                    this.cache.set(url, res);

                    resolve(res);
                }
            );

sub.unsubscribe();

More info here: http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http

Orts answered 8/4, 2016 at 3:30 Comment(7)
This answer is not longer valid in beta.15. There is no unsubscribe method in Observable now.Eipper
unsubscribe was replaced by dispose.Calciferous
I'm using RC.5 of Angular2, and unsubscribe is present (version 5.0.0-beta.6 of rxjs). Perhaps it was restored since the comments were made? Not sure where the discrepancy is coming from.Mump
@DawsonToth Angular 2 team hasn't updated rxjs from a long time, it will be updated in RC6Euxenite
could somebody provide a live example and we close the question about unsubscribe / dispose Stockbroker
What is unsubscribing all of a sudden stops cancelling the request? What can be the problem?Bedding
This is actually not correct. The service will unsubscribe before it even completes. Not sure why this was marked as correct answer by so many.Fordo
I
105

You can use the following simple solution:

if ( this.subscription ) {
   this.subscription.unsubscribe();
}
this.subscription = this.http.get( 'awesomeApi' )
 .subscribe((res)=> {
  // your awesome code..
})
Industry answered 20/10, 2016 at 9:23 Comment(11)
works great with Angular 2.4.6 - This should be the accepted answerRichthofen
Is it possible to be done via .toPromise() method and then(), catch()?Frontward
@SaeedNeamati why do you need to be done via promise ?Industry
what is the type of this.subscription??Usury
@SunilGarg are you asking for subscription: Subscription; ?Industry
I declared subscription:Subscriber<any> but this is showing error, what should be the type of this.subscriptionUsury
Maaan use a switchMap :DFlathead
Typo of this.subscription is Subscription from rxJs. I would correct first line to if ( this.subscription && !this.subscription.closed ) { to check if it was already been unsubscribedBerneicebernelle
This solution seems to be just canceling the subscription to the observable, but if the httpRequest was sent and process by the API is not really canceling the request, just the reaction - is there a way to cancel the request before if finishesFletcherfletcherism
@MauricioGraciaGutierrez Can you tell me more about your use case? Do you need this for large file uploads?Industry
I basically want to cancer the request before it finishes - I have mentioned a specific case here but is as i have mentioned - #70602275Fletcherfletcherism
O
90

You can call unsubscribe

let sub = this.http.get(url, {headers: reqHeaders})
            .subscribe(
                (res) => {
                    res = res.json();

                    this.currentLoading.delete(url);
                    this.cache.set(url, res);

                    resolve(res);
                }
            );

sub.unsubscribe();

More info here: http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http

Orts answered 8/4, 2016 at 3:30 Comment(7)
This answer is not longer valid in beta.15. There is no unsubscribe method in Observable now.Eipper
unsubscribe was replaced by dispose.Calciferous
I'm using RC.5 of Angular2, and unsubscribe is present (version 5.0.0-beta.6 of rxjs). Perhaps it was restored since the comments were made? Not sure where the discrepancy is coming from.Mump
@DawsonToth Angular 2 team hasn't updated rxjs from a long time, it will be updated in RC6Euxenite
could somebody provide a live example and we close the question about unsubscribe / dispose Stockbroker
What is unsubscribing all of a sudden stops cancelling the request? What can be the problem?Bedding
This is actually not correct. The service will unsubscribe before it even completes. Not sure why this was marked as correct answer by so many.Fordo
D
10

You can use SwitchMap on the observable which will cancel any previous request's responses and only request the latest:

https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap

Doro answered 30/1, 2018 at 13:42 Comment(1)
How? Can you give us an example?Se
F
9

A little late for the party, but here is my take:

import { Injectable } from '@angular/core'
import { Http } from '@angular/http'
import { Observable } from 'rxjs/Observable'
import { Subscriber } from 'rxjs/Subscriber'

@Injectable ()
export class SomeHttpServiceService {
  private subscriber: Subscriber<any>
  constructor(private http: Http){ }

  public cancelableRequest() {
    let o = new Observable(obs => subscriber = obs)
    return this.http.get('someurl').takeUntil(o)
      .toPromise() //I dont like observables
      .then(res => {
        o.unsubscribe
        return res
      })
  }
  public cancelRequest() {
    subscriber.error('whatever')
  }
}

This allows you to manually cancel a request. I sometimes end up with an observable or promise that will make changes to a result on the page. If the request was initiated automatically (user didn't type anyting in a field for x millis) being able to abort the request is nice (user is suddenly typing something again)...

takeUntil should also work with a simple timeout (Observable.timer) if that is what you are looking for https://www.learnrxjs.io/learn-rxjs/operators/filtering/takeuntil

Finally answered 3/8, 2017 at 9:57 Comment(2)
Why don't u like observables? For http it is the same like promise, but also has error and completeLamonicalamont
@Mick, I think clearfix was just accommodating the OP's preference for promises, not expressing his/her opinion. #theSpiritOfStackOverflowInconsumable
R
6

Use switchMap [docs], which will cancel all in-flight requests and use only the latest.

get(endpoint: string): Observable<any> {
        const headers: Observable<{url: string, headers: HttpHeaders}> = this.getConfig();
        return headers.pipe(
            switchMap(obj => this.http.get(`${obj.url}${endpoint}`, { headers: obj.headers, params: params }) ),
            shareReplay(1)
        );
    }

shareReplay will emit the latest value for any late subscribers.

Resource answered 21/5, 2019 at 11:28 Comment(1)
how to do it if I do't have any observable link your headers. I have http call made on click of button but from the docs, I can only use switchMap on observableFulmination
S
2

This is a great thread, and I have a little more info to provide. I have an API call that could potentially go on for a very long time. So I needed the previous request to cancel with a timeout. I just figured out today that I can add a timeout operator to the pipe function. Once the timeout completes its count, that will cancel the previous HTTP request.

Example...

return this.exampleHttpRequest()
  .pipe(
    timeout(3000),
    catchError(err => console.log(error)
)
Scissel answered 30/12, 2021 at 23:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.