How to cancel a pending request in an inner HTTP observable with RXJS?

Robert Lee

Cancelling a pending HTTP request when changing the page

We have an Angular service that has an expensive HTTP query that 3 different consumers can access. Each consumer can modify this query at any point, make a new request, and all other consumers must be updated with the new data.

Because HTTP subscriptions close immediately on completion, we used the inner observable pattern with behavior subjects to keep the consumers connected (see below).

The problem then, is when the user changes the page, there's no way for the current pending HTTP response to get cancelled.

Normally I don't think it would be too much of an issue to throw away an HTTP request in the background...but beyond it being an expensive operation, I have discovered if the pending response is indeed resolved after the user has returned back to the page, it'll update the consumers with data for an older query.

No bueno.

Service call

private dataSubject = new BehaviorSubject<MyData>(...);
public data$ = this.dataSubject.asObservable();
...

getData(): Observable<MyData> {
  if (this.dataSubject)
    return this.data$;
  } else {
    const http$ = this.http.post(...))
      .pipe(map(response => response as MyData),
        takeUntil(this.unsubscribe$)); // see tearDown() below
    http$.subscribe(
      (availableDevices: MyData) => {
        this.dataSubject.next(availableDevices);
      }
    );
    return this.data$;
  }
}

I attempted to create a tear down method in the service that each consumer calls during it's ngDestroy(), but it did not work unless I completed the stream. But at that point, I wasn't unable to restart the stream again when the user returns to the page.

tearDown(): void {
  this.unsubscribe$.next();
  this.unsubscribe$.complete();
  // this.dataSubject.next(null);
  // this.dataSubject.complete(); -- breaks
}

I'm by no mean an RXJS expert, so feel free to point out if my overall design is wrong. I have a nagging suspicion that I should be using switchMap() or share to prevent two consumers making the same request; but because this observable pattern is semi-hot, I'm not sure what the right course of action is. Let alone when it comes to cancelling it.

Any and all help would be appreciated.

bodorgergely

The easiest way to cancel a http call is to unsubscribe from the subscription.

const subscription: Subscription = this.http.post(...).subscribe(...);
subscription.unsubscribe();

Your teardown method is useful, and generally used as garbage collection and to cancel any pending rxjs observables. You would call it in a service/component/directive ngOnDestroy hook, so to make sure no observables remain in memory.

But if I remember correctly, angular handles http observables, so you don't need to handle them. Generally speaking you only need to take care of observables generated by yourself, like your BehaviorSubject.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Cancel pending $http request

Cancel only specific pending HTTP request with RXJS switchMap

how to cancel one of the pending http request from many angular 8

To cancel pending HTTP request & trigger fromEvent again in Angular 6 & Rxjs 6

How to cancel a composed RxJS observable

How cancel angular http request made in RXJS Effects

How to cancel pending request with jQuery in JavaScript Selenium?

How to cancel pending script tag request?

how to cancel nested request with rxjs

How to cancel in flight pending http api calls?

Angular/RxJS wait for HTTP response in inner Observable

How to cancel tcl http request

How to cancel an $http request in AngularJS?

How to cancel http request with switchMap?

How to cancel a pending signal?

Angular $http service, how to cancel / unsubscribe pending requests?

How to debug pending state of an HTTP request

How to create an RxJs Observable from a node request

How do I cancel an HTTP fetch() request?

How to cancel on-going HTTP request in Swift?

How to cancel http request in Angular 6?

How to abort/cancel HTTP request in Python thread?

How to cancel a pending wait_for

How to cancel pending requests in AngularJS?

RxJs | How to delay `mergeMap` to moment when previous inner observable completes?

rxjs: how to make foreach loop wait for inner observable

RxJs: How to only maintain the latest value until inner observable complete

RXJS observable unsubscribe inner observables

How to cancel the observable calls when exist an error in rxjs observable sequence that is requiring sequencial execution?