RxJS: Understanding the Basics of Series - 14. Subject

RxJS: Understanding the Basics of Series - 14. Subject

In this article, we will delve into the concept of Subjects in RxJS, a library for reactive programming in JavaScript. We will explore how to manually create a Subject, and then use the built-in Subject instance from RxJS to achieve the desired behavior.

Manual Realization of Subject

Before we dive into the concept of Subjects, let’s first understand the problem we are trying to solve. In the example below, we have an observable that emits values at regular intervals. We want to subscribe to this observable, but we also want to add a second observer that starts receiving values from the current element, rather than from the beginning.

const source = rxjs.interval(1000).pipe(take(3));
const observerA = {
  next: value => console.log('A next:' + value),
  error: error => console.log('A error:' + error),
  complete: () => console.log('A complete!')
};
const observerB = {
  next: value => console.log('B next:' + value),
  error: error => console.log('B error:' + error),
  complete: () => console.log('B complete!')
};
source.subscribe(observerA);
setTimeout(() => {
  source.subscribe(observerB);
}, 1000);

In the above code, we can see that observerB starts receiving values from the current element, rather than from the beginning. This is because each subscription is a separate entity, and observerB starts receiving values from the current element of the observable.

Creating a Manual Subject

To solve this problem, we can create a manual Subject that acts as a middleman between the observable and the observers. The Subject will subscribe to the observable and re-send the values to the observers.

const source = rxjs.interval(1000).pipe(take(3));
const observerA = {
  next: value => console.log('A next:' + value),
  error: error => console.log('A error:' + error),
  complete: () => console.log('A complete!')
};
const observerB = {
  next: value => console.log('B next:' + value),
  error: error => console.log('B error:' + error),
  complete: () => console.log('B complete!')
};
const subject = {
  observers: [],
  addObserver: function(observer) {
    this.observers.push(observer),
  },
  next: function(value) {
    this.observers.forEach(o => o.next(value));
  },
  error: function(error) {
    this.observers.forEach(o => o.error(error));
  },
  complete: function() {
    this.observers.forEach(o => o.complete());
  }
};
subject.addObserver(observerA);
source.subscribe(subject);
setTimeout(() => {
  subject.addObserver(observerB);
}, 1000);

In the above code, we can see that the Subject re-sends the values to the observers, and observerB starts receiving values from the current element.

Using the Built-in Subject Instance

We can also use the built-in Subject instance from RxJS to achieve the same behavior. The built-in Subject instance has the same methods as our manual Subject, and we can use it to subscribe to the observable and re-send the values to the observers.

const source = rxjs.interval(1000).pipe(take(3));
const subject = new rxjs.Subject();
const observerA = {
  next: value => console.log('A:' + value),
  error: error => console.log('Error:', error),
  complete: () => console.log('complete')
};
const observerB = {
  next: value => console.log('B:' + value),
  error: error => console.log('Error:', error),
  complete: () => console.log('complete')
};
subject.subscribe(observerA);
subject.subscribe(observerB);
source.subscribe(subject);

In the above code, we can see that the built-in Subject instance re-sends the values to the observers, and observerB starts receiving values from the current element.

What is a Subject?

A Subject is a type of observable that can act as both an observer and an observable. It can subscribe to an observable and re-send the values to other observers. This makes it a powerful tool for managing subscriptions and observers in reactive programming.

Conclusion

In this article, we have explored the concept of Subjects in RxJS and how to manually create a Subject to achieve the desired behavior. We have also seen how to use the built-in Subject instance from RxJS to achieve the same behavior. By understanding how to use Subjects, we can better manage subscriptions and observers in reactive programming.