do (tap) vs subscribe

Viewed 12111

Edit: Prior to RxJs 6, tap was called as do . Updated title to reflect tap too.

I would like to understand what is the best practice of using .subscribe and .do methods of Observables.

For example if I need to do some job after initial data is loaded from server

const init$: Observable<MyData> = this._dataService.getData();

init$
  .do((initialData: MyData) => {
    this.data = initialData; // at this step I am initializing the view
  })
  .switchMap(() => loadExtraData)
  .subscribe((extraData) => {
     doSomething(extraData, this._data); // I need this._data here
  }); 

I can do the same with .subscribe

const init$: Observable<MyData> = this._dataService.getData()
  .shareReplay(1);

init$
  .subscribe((initialData: MyData) => {
    this.data = initialData; // at this step I am initializing the view
  })

init$
  .combineLatest(loadExtraData)
  .subscribe(([initialData, extraData]) => {
     doSomething(extraData, initialData); // I need this._data here
  }); 

Which one is better and why?

4 Answers

I do everything in tap (do), because it allows to return observable, and later concat it with other additional pipes. For example, you can use tap in service, always returning observable as result. It gives you more flexibility to process it as you want, and if tomorrow you decide to add more there, you don't have refactor subscribe to tap. Finally, I put subscribe only at the final end (before rendering) with just .subscribe() (nothing in the parentheses). Also, it makes the code consistent - so you know all your side-effects are always in tap, not "something in tap and something in subscribe".

P.S. If you use Angular, often you can use | async pipe in view, which subscribes automatically, so it's one more reason to use .tap instead of .subscribe for side-effects.

Related