Getting Started with RxJS: All You Need to Know About Observables
Tags: rxjs, beginners, angular
Published: 2022-11-16 13:17:49

[RxJS](https://rxjs.dev/guide/overview) is a library that combines the Observer pattern—where Observables or Subjects notify Observers of state changes—with functional programming to handle data changes over time.

When programming with RxJS, you are usually:

- Creating Observables to subscribe later
- Creating new Observables by piping existing Observables
- Subscribing to Observables to get data

As [Observables are “the most basic building block of RxJS"](https://rxjs.dev/guide/overview), having a solid understanding of Observables is paramount to becoming proficient in RxJS.

In this blog post, you’ll learn what an Observable is, the different types of Observables and how they are helpful.

## What is an Observable?

In essence, Observables represent data (or a state) that changes over time. Observables have two critical methods you should know about: [subscribe](https://rxjs.dev/api/index/class/Observable#subscribe) and [pipe](https://rxjs.dev/api/index/class/Observable#pipe).

### Observable.subscribe()

`subscribe` will start the execution of an Observable and provides a way to observe Observable emitted notifications by passing Observer handlers.

The Observer argument of `subscribe` allows you to react when the Observable emits a new value, errors, or completes through `next`, `error`, and `complete` callbacks.

Each subscription to an Observable will create a new execution of the Observable.

```typescript
// emit sequential numbers every second and console.log that number
interval(1000).subscribe({
  next: (value) => console.log(value),
  error: () => {},
  complete: () => {},
});

// if you don't care about error or complete, you can pass only the next function:
interval(1000).subscribe((value) => console.log(value));
```
[Code Available on StackBlitz](https://stackblitz.com/edit/typescript-jdkctb?devToolsHeight=100&file=index.ts)

### Observable.pipe()

The sole reason the `pipe` method exists is to improve readability.

Without `pipe`, composing Observable streams with operators would be a nightmare. [Operators](https://rxjs.dev/guide/operators) are pure functions that take a source Observable and return a new Observable.

Imagine writing the following code to compose an Observable Stream:

```typescript
/**
 * 1. interval - emit sequential numbers every second
 * 2. map - multiply emitted values by 2
 * 3. map - emit a string `Result: ${x}`
 * 4. tap - log every emitted value
 */
tap((value) => console.log(value))(
  map((x) => `Result: ${x}`)(map((x: number) => x * 2)(interval(1000)))
).subscribe();
```

Albeit the code above is valid, the `pipe` method is always preferred.

Using the `pipe` method, the code becomes more readable:

```typescript
/**
 * 1. interval - emit sequential numbers every second
 * 2. map - multiply emitted values by 2
 * 3. map - emit a string `Result: ${x}`
 * 4. tap - log every emitted value
 */
interval(1000)
  .pipe(
     map((x) => x * 2),
     map((x) => `Result: ${x}`)
  )
  .subscribe((value) => console.log(value));
```
[Code Available on StackBlitz](https://stackblitz.com/edit/typescript-eqws53?devToolsHeight=100&file=index.ts)

## What is a Subject?

The [Subject](https://rxjs.dev/api/index/class/Subject) class extends the Observable class to allow multicasting emissions to all Observers - in other words: each new subscription to a Subject will not create a new execution of the Subject.

Subjects keep track of all their Observers.

### Subject.next(), Subject.error() and Subject.complete()

A Subject's `next`, `error`, and `complete` methods will call all of its [Observers](https://rxjs.dev/guide/observer)' `next`, `error`, and `complete` methods.

```typescript
const mySubject1 = new Subject();
const mySubject2 = new Subject();

mySubject1.subscribe({
  next: (value) => console.log(`Subject 1 Next: ${value}`),
  error: (error) => console.log(`Subject 1 Error: ${error}`),
});

mySubject1.next('A Value');
mySubject1.error('Something bad happened');

mySubject2.subscribe({
  next: (value) => console.log(`Subject 2 Next: ${value}`),
  complete: () => console.log(`Subject 2 Complete`),
});

mySubject2.complete();
```
[Code Available on StackBlitz](https://stackblitz.com/edit/typescript-fbsnht?devToolsHeight=100&file=index.ts)

### Subject.asObservable()

The `asObservable` method is useful when you want to hide the Subject’s methods when exposing it to consumers that should only use it as an Observable.

For example, you might expose the Subject in a service as an Observable, so components using that service will not be able to call the next method.

```typescript
// MyService file
const mySubject = new Subject<MyType>();

public getSubject(): Observable<MyType> {
  return this.mySubject.asObservable();
}

// MyComponent file
myService.getSubject().next();
// Property 'next' does not exist on type 'Observable<MyType>'.
```

## What is a BehaviorSubject?

`constructor(value: T)`

[BehaviorSubject](https://rxjs.dev/api/index/class/BehaviorSubject) extends Subject to ensure late subscribers are notified with the latest emitted value.

A BehaviorSubject differs from a Subject in two ways.

1. BehaviorSubject requires an initial value passed in its constructor
2. Observers will receive the latest emitted value when they subscribe to a BehaviorSubject

```typescript
const myBehaviorSubject = new BehaviorSubject('Initial Value');

myBehaviorSubject.subscribe((value) =>
  console.log(`First Subscription: ${value}`)
);

myBehaviorSubject.next('Second Value');

// a late subscription will receive the latest emitted value
myBehaviorSubject.subscribe((value) =>
  console.log(`Late Subscription: ${value}`)
);
```
[Code Available on StackBlitz](https://stackblitz.com/edit/typescript-zsa4xm?devToolsHeight=100&file=index.ts)

## What is a ReplaySubject?

`constructor(_bufferSize: number = Infinity, _windowTime: number = Infinity, _timestampProvider: TimestampProvider = dateTimestampProvider)`

[ReplaySubject](https://rxjs.dev/api/index/class/ReplaySubject) also extends Subject. ReplaySubject behaves similarly to BehaviorSubject but is capable of emitting multiple values when subscribed to.

ReplaySubject differs from BehaviorSubject in three ways:

1. A ReplaySubject does not have an initial value.
2. A ReplaySubject emits the last `bufferSize` emissions when Observers subscribe to it. Values are held in a buffer for `windowTime`.
3. A ReplaySubject still replays values for Observers even if it has been completed with an error.

```typescript
const myReplaySubject = new ReplaySubject<number>();

myReplaySubject.subscribe({
  next: (value) => console.log(`ReplaySubject Next: ${value}`),
  error: (error) => console.log(`ReplaySubject Error: ${error}`),
  complete: () => console.log(`ReplaySubject Complete`),
});

myReplaySubject.next(1);
myReplaySubject.next(2);
myReplaySubject.next(3);
myReplaySubject.error('Something bad happened');

// late subscription
myReplaySubject.subscribe({
  next: (value) => console.log(`ReplaySubject Next: ${value}`),
  error: (error) => console.log(`ReplaySubject Error: ${error}`),
  complete: () => console.log(`ReplaySubject Complete`),
});
```
[Code Available on StackBlitz](https://stackblitz.com/edit/typescript-squcej?devToolsHeight=100&file=index.ts)

## What is an AsyncSubject?

An [AsyncSubject](https://rxjs.dev/api/index/class/AsyncSubject) only emits the last value to its Observers when it completes. That’s it.

```typescript
const myAsyncSubject = new AsyncSubject();

myAsyncSubject.subscribe({
  next: (value) => console.log(`AsyncSubject Next: ${value}`),
  complete: () => console.log(`AsyncSubject Complete`),
});

myAsyncSubject.next('First Value');
myAsyncSubject.next('Second Value');

setTimeout(() => myAsyncSubject.complete(), 3000);
```
[Code Available on StackBlitz](https://stackblitz.com/edit/typescript-pmcdtd?devToolsHeight=100&file=index.ts)

## On The Road to Mastering RxJS

Now that you know how to use all the Observable Types—Observable, Subject, BehaviorSubject, ReplaySubject, and AsyncSubject—we highly recommend taking a look at the [operators' list in the official RxJS documentation](https://rxjs.dev/guide/operators#categories-of-operators), so you are at least exposed to most operators and know there’s a solution to every problem you are ever going to face.

Finally, Bitovi offers a [free RxJS course](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us) with great introductory and advanced content. You don't want to miss it. 👀

### Are Subjects a tricky subject for you?

Bitovi has expert [Angular consultants](https://www.bitovi.com/frontend-javascript-consulting/angular-consulting) ready to help you tackle your most challenging RxJS questions. Schedule your free consultation today!