# tap / do

#### signature: `tap(nextOrObserver: function, error: function, complete: function): Observable`

## Transparently perform actions or side-effects, such as logging.

***

💡 If you are using and old version of RxJS, `tap` used to be known as `do`!

***

### Why use `tap`?

Think of `tap` as a surveillance camera in a shopping mall. It doesn't interfere with the shoppers (values) moving around but merely observes and records their actions. This operator is best for side effects: actions you want to take in response to values in an observable, without affecting the values themselves.

One of the superpowers of `tap` is its utility in debugging. **When things aren't going as planned with your observable**, instead of tearing apart your chain or inserting numerous logs, simply sprinkle in some `tap` operators. It's like adding checkpoints in a video game, helping you swiftly pinpoint issues without disrupting the main flow.

However, a word of caution: **remember that `tap` is solely for side effects**. If you find yourself tempted to modify data within a `tap`, it's generally best to resist. That's not its purpose, and you're better off with [`map`](/learn-rxjs/operators/transformation/map.md) or other transformational operators in these cases.

Lastly, it's best to ensure that the side effects you introduce via `tap` are not critical to the main logic of your observable chain, keeping them non-intrusive and harmless.

### Examples

**Example 1: Logging with tap**

( [StackBlitz](https://stackblitz.com/edit/typescript-cd2gjp?file=index.ts\&devtoolsheight=100) | [jsBin](http://jsbin.com/jimazuriva/1/edit?js,console) | [jsFiddle](https://jsfiddle.net/btroncone/qtyakorq/) )

```js
// RxJS v6+
import { of } from 'rxjs';
import { tap, map } from 'rxjs/operators';

const source = of(1, 2, 3, 4, 5);
// transparently log values from source with 'tap'
const example = source.pipe(
  tap(val => console.log(`BEFORE MAP: ${val}`)),
  map(val => val + 10),
  tap(val => console.log(`AFTER MAP: ${val}`))
);

//'tap' does not transform values
//output: 11...12...13...14...15
const subscribe = example.subscribe(val => console.log(val));
```

**Example 2: Using tap with object**

( [StackBlitz](https://stackblitz.com/edit/typescript-3xykpb?file=index.ts\&devtoolsheight=100))

```js
// RxJS v6+
import { of } from 'rxjs';
import { tap, map } from 'rxjs/operators';

const source = of(1, 2, 3, 4, 5);

// tap also accepts an object map to log next, error, and complete
const example = source
  .pipe(
    map(val => val + 10),
    tap({
      next: val => {
        // on next 11, etc.
        console.log('on next', val);
      },
      error: error => {
        console.log('on error', error.message);
      },
      complete: () => console.log('on complete')
    })
  )
  // output: 11, 12, 13, 14, 15
  .subscribe(val => console.log(val));
```

### Related Recipes

* [Battleship Game](/learn-rxjs/recipes/battleship-game.md)
* [Breakout Game](/learn-rxjs/recipes/breakout-game.md)
* [Car Racing Game](/learn-rxjs/recipes/car-racing-game.md)
* [Catch The Dot Game](/learn-rxjs/recipes/catch-the-dot-game.md)
* [Click Ninja Game](/learn-rxjs/recipes/click-ninja-game.md)
* [Flappy Bird Game](/learn-rxjs/recipes/flappy-bird-game.md)
* [Horizontal Scroll Indicator](/learn-rxjs/recipes/horizontal-scroll-indicator.md)
* [Lockscreen](/learn-rxjs/recipes/lockscreen.md)
* [Memory Game](/learn-rxjs/recipes/memory-game.md)
* [Mine Sweeper Game](/learn-rxjs/recipes/mine-sweeper-game.md)
* [Platform Jumper Game](/learn-rxjs/recipes/platform-jumper-game.md)
* [Save Indicator](/learn-rxjs/recipes/save-indicator.md)
* [Space Invaders Game](/learn-rxjs/recipes/space-invaders-game.md)
* [Stop Watch](/learn-rxjs/recipes/stop-watch.md)
* [Swipe To Refresh](/learn-rxjs/recipes/swipe-to-refresh.md)
* [Tank Battle Game](/learn-rxjs/recipes/tank-battle-game.md)
* [Tetris Game](/learn-rxjs/recipes/tetris-game.md)
* [Type Ahead](/learn-rxjs/recipes/type-ahead.md)
* [Uncover Image Game](/learn-rxjs/recipes/uncover-image-game.md)

### Additional Resources

* [tap](https://rxjs.dev/api/operators/tap) 📰 - Official docs
* [Logging a stream with do](https://egghead.io/lessons/rxjs-logging-a-stream-with-do?course=step-by-step-async-javascript-with-rxjs) 🎥 💵 - John Linquist
* [Utility operator: do](https://egghead.io/lessons/rxjs-utility-operator-do?course=rxjs-beyond-the-basics-operators-in-depth) 🎥 💵 - André Staltz

***

> 📁 Source Code: <https://github.com/ReactiveX/rxjs/blob/master/packages/rxjs/src/internal/operators/tap.ts>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.learnrxjs.io/learn-rxjs/operators/utility/do.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
