do (tap) vs subscribe

一曲冷凌霜 提交于 2019-12-12 09:34:35

问题


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?


回答1:


Edit: For RxJS 6 or above, Read do as tap.

do is used for side-effects. subscribe is used to invoke an observable. Replacing do with subscribe creates undesired results. Replacing subscribe with do will not even invoke the stream.

Consider these examples :

Using subscribe :

const testObservable = Rx.Observable.create(function(observer){
   console.log('some heavy task, may be network call ');
   observer.next('success');
});

testObservable.subscribe(function(res){
    console.log('action 1');
});

testObservable.subscribe(function(res){
   console.log('action 2');
});

The output of the above code is

"some heavy task, may be network call "
"action 1"
"some heavy task, may be network call "
"action 2"

You can see the Rx.Observable.create got executed twice. Our goal is do it only once but along with action 2, do action 1 also.

Using do:

const testObservable = Rx.Observable.create(function(observer){
   console.log('some heavy task, may be network call ');
   observer.next('success');
});

testObservable
    .do(function(res){
        console.log('action 1');
    })  
    .subscribe(function(res){
        console.log('action 2');
    });

The output would be

"some heavy task, may be network call "
"action 1"
"action 2"

This is what we actually wanted. We need 'action 2' but before that do 'action 1' also.

Why is it called side effect:

Because it will not affect the flow of stream unlike other operators. It takes the response , does something and even if it modifies the response the stream is going to ignore it . For ex:

testObservable
    .do(function(res){
        console.log('action 1');
        return res+'some other text';
    })  
    .subscribe(function(res){
        console.log('action 1');
    });

The above code will still give the same output as before. So no matter what you execute in do the stream is going to ignore it and proceed with its execution.

If we are doing pure 'functional reactive programming' we don't want any side effects in the stream. So, do is discouraged and mostly used only for debugging purposes .




回答2:


The Observable chain is not going to do anything until you use subscribe() that makes connections between operators. So you always have to use the subscribe() method.

The do() operator is intended to only make side-effects.

In my experience it's often not possible to do everything in subscribe() and you sometimes need to use do() because your application logic needs to make actions in a specific order.

So in general I'd try to avoid using do() and put most of my logic into subscribe(). Only if I had to perform actions in a different order I'd use do().




回答3:


Hardly in any case you need subscribe in a service. If your data flow is done in a really reactive way, you only subscribe in consumers (who are represented by components in Angular) to run the whole stream shebang. This allows stream composition which is a basis of the reactive approach. Avoid saving something from an observer into local scope, it's also against stream purity. You may rather compose a stream to pass all necessary data or combine streams.



来源:https://stackoverflow.com/questions/45321516/do-tap-vs-subscribe

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