简体   繁体   中英

Why does my rxjs subscription fail to close after completing

We have an rxjs subscription that's failing to close. I'm wondering if this is a bug in the rxjs library or if we're doing something wrong.

Our code looks like this:

  private loadGroups(): void {
    if (this.groupOptionsSubscription?.closed === false){
      this.groupOptionsSubscription.unsubscribe();
    }
    this.groupOptionsSubscription =
      this.lookupService
        .getGroupLookups(null, this.filter.companyId)
        .pipe(debounceTime(environment.filterDelay))
        .subscribe(
          (groups) => {
            this.groupOptions$.next(groups);

            setTimeout(() => {
              console.log(this.groupOptionsSubscription.closed);
            }, 5000);
        });
  }

In this method, there is a subscription called groupOptionsSubscription . It first checks if it's not closed (or exists). If it is not closed (and it exists), we unsubscribe (which closes it immediately). Then we assign it to a new subscription that comes from this.lookupService.getGroupLookups() . When the observable fires, the subscribe callback runs. Once the callback is finished, the subscription should close (right?). Most of the time it does, but sometimes it doesn't. I can test this by console logging the closed state of the subscription in a 5 second timeout. About 1 in 5 times, it shows that the subscription is not closed.

This method can be called more than once before the previous observables fire. For example, it can be called 3 times, and only after the third time will the subscription callback run, with the previous two network requests being canceled and the previous two subscriptions being (I guess) disposed. In other words, only the last one completes. I have verified that it is this last one which also (sometimes) fails to close.

Does anyone know why this might be happening? Is this a known bug with the rxjs library? Or does it have something to do with the way we're handling subscriptions? Thanks.

Maybe there's something in getGroupLookups that's causing the observable to stay open? You could add a take(1) to the pipe, but here's the thing, rxjs already has mechanisms to manage subscriptions. So instead of trying to keep track if a subscription is open or closed, just use what rxjs already has.

readonly loadGroupsSubject = new Subject();
readonly groupOptions$ = this.loadGroupsSubject().pipe(
  switchMap(() => this.getGroupLookups(null, this.filter.companyId)),
  debounceTime(environment.filterDelay)
);
  1. switchMap will cancel the previous emission if it's still open and start a new one. No need to check if a subscription is closed.
  2. You can add a take(1) inside the switchMap if getGroupLookups really is staying open and is causing a problem.
  3. Add shareReplay(1) if you want to share the result with multiple subscribers and you want late subscribers to have access to the last result.
  4. You could create a function that calls loadGroupsSubject and returns a reference to groupOptions$ , but there isn't much point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM