In this article, we’ll create a simple implementation of the observable pattern and work to understand the core concepts behind it.

The Observer pattern:

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and automatically notifies them of any state changes (usually by calling one of their methods). (Wikipedia)

The observable object represents a push-based collection. Observables are just what you’d imagine — things you wish to observe and take action on.

The observable object class sends notifications, while the observer object class receives them.

Let’s start by defining the observable class.

The Observable class considers one parameter — a subscription function. The subscription function is named as such because this is the function that invokes our observable when someone calls subscribe() .

Sometimes people refer to the subscription function as the “producer” function, because this function also produces the values for the observer.

Let’s create a new instance of our Observable .

A subscription function receives an observer. An observer is simply a plain object with three optional methods: next() , error() , and complete() .

next() : Call this method when you have a new value.

: Call this method when you have a new value. error() : Call this method on error.

: Call this method on error. complete(): Call this method on complete.

As you can imagine, in this phase we still don’t invoke anything. Observables are lazy — nothing executes until we call subscribe() . (in case of cold observables)

Let’s create the subscribe() method.

The subscribe() method takes an observer and calls the subscription function with it. Note that each call to subscribe() invokes the subscription function again.

Let’s continue by creating an interval observable.

When we subscribe to the interval observable we are invoking the subscription function, that executes the native JS setInterval() function and notifies the observer each time it’s invoked.

But that’s not enough. We should also be able to “stop” the subscription function. Each observable should return the unsubscribe() method responsible for cleaning.

The unsubscribe() method of our interval stops the interval by calling clearInterval() with the provided ID.

Operators

Operators are observables that operate on a source observable. Let’s create the map() operator.

Now, let’s see how we can use this operator with our interval observable.

The map() operator returns a new Observable that subscribes to the source — in our case, the interval observable.

When the source emits a new value, the value first gets to the map() subscription function. Then, after applying the projection function on the value, the map() observable emits the value to the final subscription.

This is called the Observable chain.