Linked Questions

Popular Questions

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.

Related Questions