tap() vs subscribe() to set a class property

倖福魔咒の 提交于 2019-11-29 02:37:48

问题


I am very new to rxjs and was just wondering is it ok to setup a class property by piping the stream and tapping it, or it should i do it in the subscribe. To me either way works, just wonder if it is ok to do it as I see fit to my eyes or there is something I am unaware of.

Typescript code demonstrating both ways:

export class ViewComponent implements OnInit {

  applicant = {};

  constructor(public route: ActivatedRoute, private store: Store<any>) {}

  ngOnInit() {
    this.route.paramMap.pipe(
      switchMap(params => this.store.select(state => state.applicants.entities[params.get('id')])),
      tap(applicant => this.applicant = applicant)
    ).subscribe();
  }
}

vs

export class ViewComponent implements OnInit {

  applicant = {};

  constructor(public route: ActivatedRoute, private store: Store<any>) {}

  ngOnInit() {
    this.route.paramMap.pipe(
      switchMap(params => this.store.select(state => state.applicants.entities[params.get('id')]))
    ).subscribe(applicant => this.applicant = applicant);
  }
}

回答1:


Good question. In the source code for the tap operator, this comment pretty much sums it up:

This operator is useful for debugging your Observables for the correct values or performing other side effects.
Note: this is different to a subscribe on the Observable. If the Observable returned by do is not subscribed, the side effects specified by the Observer will never happen. do therefore simply spies on existing execution, it does not trigger an execution to happen like subscribe does.

Any side effect you can run in a tap can probably also be put in the subscribe block. The subscribe indicates your intent to actively use the source value since it's saying "when this observable emits, I want to save it's value in the applicants variable". The tap operator is mostly there for debugging, but it can be used to run side effects.

In general, favor the subscribe block for running side effects, use tap for debugging, but be aware that tap can do more if you need it to.




回答2:


tap is useful when you have the observable separated from its subscriber. If you have a class that exposes an observable, you can use tap to implement side effects that this class needs to be executed when someone is listening to the observable. In the other side, when you subscribe to it from another class, you can implement side effects from the subscriber's point of view, using subscribe.

Class with the observable:

public dummyObservable: Observable<number> = from([1, 2, 3, 4, 5]).pipe(
  // Side effects, executed every time I emit a value
  // I don't know which side effects implements who subscribes to me
  tap( n => console.log("I'm emitting this value:", n) )
);

Class with the subscription:

ngOnInit(): void {
  this.dummyService.dummyObservable.subscribe(
    // Side effects, executed every time I receive a value
    // I don't know which side effects implements the observable
    data => console.log("I'm receiving this value: ", data)
  );
}



回答3:


Michael Hladky suggests that you put all side effects in the tap operator and he explains why here.

I think it's generally a good idea to do so, because as Michael says, you can then merge many observables together and create one single subscription for all of them.

I don't know if this improves performance or not, but it definitely makes it easier when you want to unsubscribe to only have one subscription. Unsubscribing is something you always should do to avoid possible memory leaks or other strange behaviors.

Another gain from this approach is that you then easily can pause, resume or complete a group of observables by piping it through operators such as filter or takeWhile, or by switchmapping it through another observable like this:

const allMergedObservables$ = merge(obs1, obs2, obs3);
const play$ = new Subject();

play$.asObservable().pipe(
    switchMap(bool => bool ? allMergedObservables$ : EMPTY)
).subscribe();

// Putting 'true' into the play stream activates allMergedObservables$. 
play$.next(true);

// Something happens that makes you want to pause the application,
// for instance the user opens the print dialog box,
// so you issue 'false' in the play stream which in turn stops the
// inner subscription of allMergedObservables$:
play$.next(false);

However, it's up to you and whatever programming style you prefer.



来源:https://stackoverflow.com/questions/49184754/tap-vs-subscribe-to-set-a-class-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!