14

I have a quick question about observable.

I have the following observable:

  getElevation(pos: Cartographic): Observable<Cartographic> {
    return new Observable(observer => {
      const promise = Cesium.sampleTerrain(this.terrainProvider, 11, Cesium.Cartographic(pos.longitude, pos.latitude))
      Cesium.when(promise, (updatedPositions) => {
        observer.next(updatedPositions);
        observer.complete();
      });
    });
  }

In a component I have:

this.service.getElevation(value).subscribe((e) => {});

My question is, this is a one shoot observable, so I complete just after, is the complete automatically close the subscription? or, do I also have to do this:

const sub = this.service.getElevation(value).subscribe((e) => {sub.unsubscribe();});
Aviv
  • 129
  • 1
  • 11
Bobby
  • 4,372
  • 8
  • 47
  • 103
  • https://stackoverflow.com/questions/48771350/rxjs-subscriber-unsubscribe-vs-complete – martin Jun 26 '19 at 07:45
  • https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription?rq=1 – martin Jun 26 '19 at 07:46

3 Answers3

12

In your case you don't need to unsubscribe.

All Observers will automatically be unsubscribed when you call complete. That said, you may want to implement your consuming (component) code do handle the possibility that the implementation of the service may change in the future.

You could do this by using the take operator which will unsubscribe after the first value is emitted:

this.service.getElevation(value).pipe(take(1)).subscribe((e) => {});
Will Taylor
  • 1,650
  • 9
  • 23
4

You should not unsubscribe in a subscription, it the observable emits instantly then sub is undefined.

If you want a self unsubscribing observable you can use takeUntil

finalise = new Subject();
this.service.getElevation(value).pipe(takeUntil(finalise)).subscribe((e) => { 
  finalise.next();
  finalise.complete();
});
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • Wouldn't this be equivalent to `this.service.getElevation(value).pipe(take(1)).subscribe((e) => {});` – Will Taylor Jun 26 '19 at 13:07
  • 2
    The difference is that you can control when finalise is called, usually in ngOnDestroy. The problem with take 1 is that you cannot be guaranteed that the observable has emitted and might fire after you expect. In this circumstance it basically is equivalent, but the call to finalise should usually be made in a deconstructor. – Adrian Brand Jun 26 '19 at 22:01
3

Brief note:

  • Try to control the subscription with operators such as takeUntil.
  • You don’t need to unsubscribe yourself if the sender(Subject) completes.
  • For your case, since the sender returned by getElevation function completes itself after emitting a value one time, you don’t need to either use any operator or unsubscribe yourself to unsubscribe it.

All you have to do: this.service.getElevation(value).subscribe((v) => // do what you want);

DongBin Kim
  • 1,799
  • 5
  • 23
  • 43