Skip to content Skip to sidebar Skip to footer

Do (tap) Vs Subscribe

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 Observa

Solution 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 .

Solution 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().

Solution 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.

Solution 4:

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.

Post a Comment for "Do (tap) Vs Subscribe"