Mastering Real-Time Magic: The Observer Pattern
Tags: javascript, programming, tutorial, designpatterns
Published: 2023-10-30 07:30:00

## What is the Observer Pattern ?
At its core, the Observer pattern establishes a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically. This pattern is ideal for scenarios where an object's state change should trigger specific actions in other parts of the code.


![Observer pattern schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wsem6jegj830xj3y13a1.png)

---

## Real use case : Real-Time Dashboard

### The Observable Class

```js
class Observable {
  constructor() {
    this.observers = [];
  }

  subscribe(callback) {
    this.observers.push(callback);
  }

  unsubscribe(callback) {
    this.observers = this.observers.filter(observer => observer !== callback);
  }

  notify(data) {
    this.observers.forEach(observer => observer(data));
  }
}

export default Observable;
```
In this implementation, we've defined an Observable class with methods to **subscribe**, **unsubscribe**, and **notify** observers.

### Integrating the Observer Pattern

Now, let's use the Observer pattern to create a real-time dashboard with three data sources: stock prices, weather updates, and news alerts.

#### Stock Price
```js
const stockObserver = new Observable();

function updateStockPrices(price) {
  console.log(`Stock Price: $${price}`);
}

stockObserver.subscribe(updateStockPrices);

// Simulate real-time updates
setInterval(() => {
  const newPrice = Math.random() * 100;
  stockObserver.notify(newPrice);
}, 2000);
```

#### Weather Updates
```js
const weatherObserver = new Observable();

function updateWeather(weatherData) {
  console.log(`Weather Update: ${weatherData}`);
}

weatherObserver.subscribe(updateWeather);

// Simulate real-time updates
setInterval(() => {
  const newWeather = 'Sunny';
  weatherObserver.notify(newWeather);
}, 3000);
```

#### News Alerts
```js
const newsObserver = new Observable();

function updateNews(news) {
  console.log(`News Alert: ${news}`);
}

newsObserver.subscribe(updateNews);

// Simulate real-time updates
setInterval(() => {
  const headlines = ['Breaking News 1', 'Breaking News 2', 'Breaking News 3'];
  const randomNews = headlines[Math.floor(Math.random() * headlines.length)];
  newsObserver.notify(randomNews);
}, 5000);
```

By implementing the Observer pattern, we've achieved a real-time dashboard that updates stock prices, weather conditions, and news alerts as soon as new data is available.

---

## Going further with a more complex example

```js
// Subject - Blog class
class Blog {
  constructor() {
    this.subscribers = [];
  }

  // add a subscriber (observer)
  subscribe(subscriber) {
    this.subscribers.push(subscriber);
  }

  // remove a subscriber (observer)
  unsubscribe(subscriberToRemove) {
    this.subscribers = this.subscribers.filter(subscriber => subscriber !== subscriberToRemove);
  }

  // Notify when there is a new article
  publishNewArticle(article) {
    this.subscribers.forEach(subscriber => {
      subscriber.notify(article);
    });
  }
}

// Observer - Subscriber class
class Subscriber {
  constructor(name) {
    this.name = name;
  }

  // notification method
  notify(article) {
    console.log(`${this.name} got a notification : new article! - "${article}"`);
  }
}

// Let's create a blog
const myBlog = new Blog();

// With three random users
const subscriber1 = new Subscriber('Alice');
const subscriber2 = new Subscriber('Bob');
const subscriber3 = new Subscriber('Charlie');

// The subscribers join to the blog
myBlog.subscribe(subscriber1);
myBlog.subscribe(subscriber2);
myBlog.subscribe(subscriber3);

// New article!
myBlog.publishNewArticle('Les dernières tendances en programmation');

// Result : Each subscriber got a notification

// Unsubscribe a user
myBlog.unsubscribe(subscriber2);

// New article!
myBlog.publishNewArticle('Guide de démarrage rapide en développement web');

// Result : Only Alice AND Charlie got a notification.
```

---

## Benefits of the Observer Pattern

1 - **Real-Time Updates**: The Observer pattern enables real-time updates **across various parts of your application**, providing a seamless and responsive user experience.

2 - **Decoupled Code**: Objects are loosely coupled, making it easy to add or remove observers **without affecting other parts of the code**.

3 - **Customizable Reactions**: Observers can define **custom reactions to changes**, allowing for **flexibility** and **extensibility**.

--- 

## Conclusion
The Observer pattern is a valuable addition to your JavaScript toolkit, particularly when you need real-time updates and efficient communication between components. As demonstrated through our real-time dashboard example, it ensures that changes in one part of your application immediately affect other dependent parts, resulting in a more interactive and dynamic user experience.