Basic RxJS Operators and How To Use Them
Tags: javascript, rxjs, operators, tutorial
Published: 2020-12-03 09:28:39

In our Getting Started With RxJS article, we briefly mentioned [Operators](https://www.learnrxjs.io/learn-rxjs/operators). In this article, we will expand further on what Operators are in [RxJS](https://rxjs.dev/). We will also show you some basic Operators, what they do, and how you can use them.

## What _are_ RxJS Operators?

Taken straight from the [RxJS manual](http://reactivex.io/rxjs/manual/overview.html#operators):

> Operators are the essential pieces that allow complex asynchronous code to be easily composed in a declarative manner.

If you're scratching your head, don't worry. I think most people would be confused by that statement alone. Luckily for us, the manual gives an even better definition:

> An Operator is a function which creates a new Observable based on the current Observable. This is a pure operation: the previous Observable stays unmodified.

Essentially, an Operator is like a machine that takes an [Observable](http://reactivex.io/rxjs/manual/overview.html#observable) as an input, performs some logic on the values streamed through the Observable, and creates a new Observable with these values, without changing the original Observable.

The diagram below might help illustrate it a little better.

![Operator Explanation](//images.ctfassets.net/zojzzdop0fzx/3ZyUE31GtnymdJZB6CewHk/7c91f69246f2c21a99c034864a755417/OperatorExplanation.png)

We can see that the Operator takes in the values from one Observable, and creates a new Observable that emits altered values of the original Observable's values, without affecting the original Observable.

Now let's take a look at 6 basic Operators: `of`, `from`, `map`, `tap`, `switchMap`, `take`.

## 1. `of` - Creation Operator

The [of](https://www.learnrxjs.io/learn-rxjs/operators/creation/of) Operator is a creation Operator. Creation Operators are functions that create an Observable stream from a source.

The `of` Operator will create an Observable that emits a variable amount of values in sequence, followed by a Completion notification.

_A Completion notification tells the Observable's subscribers that the Observable will no longer be emitting new values. We will cover this in more detail in a future article!_

Let's take a look at `of` in practice.

```js
const arr = [1, 2, 3];

const arr$ = of(arr);

arr$.subscribe((values) => console.log(`Emitted Values: `, values));

```

`of` creates the Observable, and when we subscribe to it, it starts emitting its values immediately.  

The output of the above is:

```
Emitted Values: [1, 2, 3]
```

`of` will emit the full array `[1, 2, 3]` as a full value. This is in contrast to `from`, which we will look at next!

## 2. `from` - Creation Operator

The [from](https://www.learnrxjs.io/learn-rxjs/operators/creation/from) Operator turns an Array, Promise, or Iterable, into an Observable. 

This operator will convert a Promise to an Observable, allowing for it to be handled in a more reactive manner. When the Promise resolves or rejects, a completion notification will be sent to any subscribers.

Also, unlike `of`, it will emit each element in an Array or Iterable in sequence, rather than the full value. Once all elements of the Array or Iterable have been emitted, a completion notification is sent to any subscribers.

Let's take the example we used for `of` to see this difference in action:

```js
const arr = [1, 2, 3];

const arr$ = from(arr);

arr$.subscribe((values) => console.log(`Emitted Values: `, values));
```

Its output is:

```
Emitted Values:  1
Emitted Values:  2
Emitted Values:  3
```

As we can see by the multiple logs, the `from` Operator took each number and emitted it as a value. The subscriber received each value in sequence, and called `console.log` three times.

We can also use a value such as a string:

```js
const fromString$ = from("Hello");
fromString$.subscribe((value) => console.log(`Emitted Values: `, value));
```

The output is:

```
Emitted Values:  H 
Emitted Values:  e 
Emitted Values:  l 
Emitted Values:  l 
Emitted Values:  o 
```

How about for a Promise? Let's take a look!

```js
const examplePromise = new Promise((resolve, reject) => {
  // Do some async code and resolve and object with an id property
  return resolve({ id: 1 });
});

const promise$ = from(examplePromise);
promise$.subscribe((value) => console.log(`Emitted Values: `, value));
```

The output of this would be:

```
Emitted Values:  {id: 1}
```

When the Promise resolves, the value gets emitted as the next value in the Observable.

## 3. `map` - Transformation Operator

The [map](https://www.learnrxjs.io/learn-rxjs/operators/transformation/map) operator is a Transformation Operator. It takes values from one Observable, transforms them, and creates a new Observable that emits the transformed values.

With `map`, you can perform simple transformations to the values emitted by an Observable. Let's take a look at two examples.

For the first example, we'll take the Array example for the `from` Operator, and modify it to also use `map`:

```js
const arr = [1, 2, 3];

const fromArr$ = from(arr);

fromArr$
  .pipe(map((value) => value + 10))
  .subscribe((value) => console.log(`Emitted Values: `, value));
```

_You'll notice the introduction of the `.pipe()` call. This is RxJS's method for applying operators to an Observable's stream before you subscribe to it. It will pipe the value emitted from the Observable through each operator passed as an argument, before passing the final transformed value to the `subscribe` method. We'll cover this in more detail in a future article!_

In this example, as `map` is a transformation Operator, it must be used within the `.pipe()` call so that it can transform the value it receives from the Observable. We are simply adding 10 to the value, and emitting the transformed value.

You can see this in the output:

```
Emitted Values:  11
Emitted Values:  12
Emitted Values:  13
```

We can do almost anything in the `map` Operator, but a common use-case would be to get a property from an object that is emitted in an Observable stream. We can use our Promise example to see this in action:

```js
const examplePromise = new Promise((resolve, reject) => {
  // Do some async code and resolve and object with an id property
  return resolve({ id: 1 });
});

const promise$ = from(examplePromise);
promise$
  .pipe(map((obj) => obj.id))
  .subscribe((value) => console.log(`Emitted Values: `, value));
```

Here, we are telling the `map` operator to return the `id` property of the object that is resolved in the Promise. The output of this is:

```
Emitted Values:  1
```

The `map` Operator is a commonly used Operator and is very useful for a number of use-cases!

## 4. `switchMap` - Transformation Operator

The [switchMap](https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap) operator is another transformation Operator.

`switchMap` receives the values emitted by an Observable, and then returns a new Observable from a different source. 

Let's say you have an Observable that emits User IDs. You may want to fetch the full User object correlating to the ID, then do something with the full details. The `switchMap` operator would receive the ID from the Observable, then return an Observable containing the response from the request to fetch the User object.

I find it can be useful to think of this in the terms of `switching streams`. You're switching from one Observable stream to another.

Let's take a look at an example:

```js
const userDetails$ = from(this.userService.getActiveUserID())
    .pipe(switchMap(id => this.userService.fetchUserForID(id)))
    .subscribe(user => console.log("Found user ", user));
```
Here, we ask for the active user's ID. Then, we ask the `userService` to make an ajax request to our backend to fetch the User that correlates with the ID. We are assuming that the `fetchUserForID` call returns an Observable. _(This can be possible with the [ajax](https://www.learnrxjs.io/learn-rxjs/operators/creation/ajax) operator which we will discuss in a future article!)_

We then subscribe to this new Observable stream, and receive the value it emits, rather than the values emitted from `from(this.userService.getActiveUserID())` as seen in the output:

```
Found user  {id: 1, name: "Test User", email: "test@test.com"}
```

It's worth noting that the `switchMap` operator will cancel any in-flight network requests if it receives a new value from the original _(commonly known as the source)_ Observable stream, making it a great candidate for typeahead search implementations!

## 5. `tap` - Utility Operator

The [tap](https://www.learnrxjs.io/learn-rxjs/operators/utility/do) Operator is a Utility Operator which is very similar to a helper function, except in the reactive programming landscape.

`tap` allows you to perform actions or side effects on an Observable stream **without** modifying or altering the original stream. The values "pass-through" the `tap` Operator to the next Operator or Subscriber.

This can be very useful for logging:

```js
const arr = [1, 2, 3];

const fromArr$ = from(arr);

fromArr$
  .pipe(tap((value) => console.log("Received value: ", value)))
  .subscribe((value) => console.log(`Emitted Values: `, value));
```

Which would output:

```
Received value:  1
Emitted Values:  1

Received value:  2
Emitted Values:  2

Received value:  3
Emitted Values:  3
```

## 6. `take` - Filtering Operator

The [take](https://www.learnrxjs.io/learn-rxjs/operators/filtering/take) operator is a [Filtering Operator](https://www.learnrxjs.io/learn-rxjs/operators/filtering). Filtering Operators allows you to select how and when to accept values emitted from Observables.

`take` is one of the most common and most simplistic filtering Operators. It allows you to specify a maximum number of values you want to receive from an Observable.

We can use our `from` example where we emit the elements of an Array, and combine it with `take` to get a better understanding of this operator:

```js
const arr = [1, 2, 3];

const fromArr$ = from(arr);

fromArr$
  .pipe(take(1))
  .subscribe((value) => console.log(`Emitted Values: `, value));

```

From the output below we can see we only received and used 1 value from the array:

```
Emitted Values:  1
```

It can be used in situations where we want to limit how many user-produced events (`fromEvent`) we want to handle, for example, the first time the user clicks in our app.

## Conclusion

In this article, we briefly covered some of what I would consider to be the most common Operators that live in RxJS. By understanding these 6 Operators, you are on your way to mastering RxJS! Stay tuned for more articles discussing more operators and more in-depth topics based on RxJS.

---
*This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit [thisdotlabs.com](https://www.thisdotlabs.com).*

*This Dot Media is focused on creating an inclusive and educational web for all.  We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit [thisdot.co](https://www.thisdot.co).*