rxjs

observable.subscribe(..).unsubscribe(); anti-pattern.


I've been finding myself writing code that looks like this:

class WidgetService {

   getWidgets() {
       return this.authService.user.pipe(  //authService.user is an Observable, that emits the currently authenticated users. 
         first(user => user!=null),  //Make sure a null object isn't coming through
         switchMap(user => {
            return this.collection.getWhere("widget.ownerId", "==", user.id); //Get all the widgets for that user
         })
       ); 
   }

}

class WidgetDisplayComponent {

    ngOnInit() {
       this.widgetService.getWidget().subscribe(widget => this.widget = widget).unsubscribe(); //Subscribe to cause the Observable to pipe, get the widget, then unsubscribe. 
    }
}

Is this an anti pattern? What should I be doing instead, where the requirements are:


Solution

  • I would say that it is absolutely an anti-pattern, for these reasons:

    The pattern would only work for synchronous sources that emit only a single next notification. In which case, the unsubscribe is redundant, as the subscriber will be automatically unsubscribed when the source completes.

    IMO, if you know that the source emits only one next notification, you should just omit the unsubscribe. If you are unsure, you should use either first or take(1) at the subscription point.


    There is another mechanism that can be used to unsubscribe upon receipt of the first next notification, but it's not one that I would encourage, as it requires a non-arrow function to be used.

    The subscriber is used as the context when the next handler is invoked, so it's possible to call unsubscribe on it, like this:

    source.subscribe(function (value) {
      /* do something with value */
      this.unsubscribe();
    });