{"id":7997,"date":"2020-07-23T06:22:00","date_gmt":"2020-07-23T11:22:00","guid":{"rendered":"https:\/\/upmostly.com\/?p=7997"},"modified":"2022-11-01T09:31:05","modified_gmt":"2022-11-01T14:31:05","slug":"what-does-the-tap-operator-do-in-angular-rxjs","status":"publish","type":"post","link":"http:\/\/upmostly.com\/angular\/what-does-the-tap-operator-do-in-angular-rxjs","title":{"rendered":"What Does The Tap Operator Do In Angular\/RxJS"},"content":{"rendered":"\n<p>I was working with a piece of code recently that made liberal use of the \u201cTap\u201d operator on an observable. I\u2019ve seen it used pretty often, but everytime I try and find documentation to show a junior developer how it works, I always find it a really overcomplicated mess. Tap, infact, is a really simple operator on the surface that you really shouldn\u2019t have a hard time understanding.<\/p>\n\n\n\n<p>Let\u2019s jump straight into some code. The most common use-case for using tap is because you want to use the result of an observable elsewhere, but still pass the exact same result back to any subscriber.<\/p>\n\n\n\n<p>For instance let\u2019s say that I want to call an API to fetch the current user, and I want to do nothing more than log that user to the console, and then return that same user out. A very naive way to achieve this would be :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">this.http.get&lt;User&gt;('api\/user').pipe(map((user : User) =&gt; {\n\tconsole.log(`Current User Is : ${user.name}`)\n\treturn user;\n}));<\/code><\/pre>\n\n\n\n<p>Theoretically not a heck of a lot wrong with this, I mean it works, but it\u2019s not nice. You are calling the map function purely so that you can log the user, but then you aren\u2019t actually mapping anything, and instead returning the same user. The result of this function is still Observable&lt;User&gt; so the caller doesn\u2019t know what\u2019s going on behind the scenes, but it\u2019s messy.<\/p>\n\n\n\n<p>One of the worst ways I\u2019ve seen someone try and achieve this looked like so :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">return Observable.create((observer: Observer&lt;User&gt;) =&gt; this.http.get&lt;User&gt;('api\/user').subscribe((user : User) =&gt; {\n\tconsole.log(`Current User Is : ${user.name}`)\n\tobserver.next(user)\n\tobserver.complete()\n}));<\/code><\/pre>\n\n\n\n<p>I mean talk about RxJS word salad. It\u2019s a mess. And we don\u2019t need to do this if we just use Tap!<\/p>\n\n\n\n<p>Taking the above example and using Tap.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">this.http.get&lt;User&gt;('api\/user').pipe(tap(user =&gt; { \n\tconsole.log(`Current User Is : ${user.name}`) \n}));<\/code><\/pre>\n\n\n\n<p>Notice how we used tap to write the console log, but we didn\u2019t have to return the user object. It\u2019s because we are saying that Tap will do something with the user object, but the original user should be returned to whoever is subscribing.<\/p>\n\n\n\n<p>Another way to remember what tap does is that you are \u201ctapping\u201d into the result. Like a wiretap almost! You are listening in but (theoretically), you aren\u2019t interfering with the existing conversation.<\/p>\n\n\n\n<p>There is one caveat when using Tap though, and that is that the object inside the tap is still a reference to the original, it\u2019s not a clone. So for example :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">\/\/This will return a user object with the firstName of test. \nthis.http.get&lt;User&gt;('api\/user').pipe(tap(user =&gt; { \n\tuser.firstName = 'Test';\n}));<\/code><\/pre>\n\n\n\n<p>I personally prefer to use Tap only when the method inside the tap is safe and has no side effects that would alter the original result. If I am going to be altering the original result, I prefer to use the Map operator because that signals that we are \u201cmapping\u201d what the original result was to something new (Even if it\u2019s only changing a single property).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was working with a piece of code recently that made liberal use of the \u201cTap\u201d operator on an observable. I\u2019ve seen it used pretty often, but everytime I try and find documentation to show a junior developer how it works, I always find it a really overcomplicated mess. Tap, infact, is a really simple [&hellip;]<\/p>\n","protected":false},"author":131,"featured_media":8000,"comment_status":"open","ping_status":"open","sticky":false,"template":"post-tutorial-new.php","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[150],"tags":[],"class_list":["post-7997","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular"],"acf":[],"_links":{"self":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts\/7997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/users\/131"}],"replies":[{"embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/comments?post=7997"}],"version-history":[{"count":3,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts\/7997\/revisions"}],"predecessor-version":[{"id":13290,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts\/7997\/revisions\/13290"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/media\/8000"}],"wp:attachment":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/media?parent=7997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/categories?post=7997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/tags?post=7997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}