Hone logo
Hone
Problems

Implementing the Observable Pattern in JavaScript

The Observable pattern is a behavioral design pattern that allows one object (the subject) to notify multiple observers of any state changes. This is a fundamental pattern for building reactive systems and event-driven architectures, commonly used in UI frameworks and data synchronization. Your task is to implement a basic Observable pattern in JavaScript.

Problem Description

You need to create a JavaScript class named Observable that allows objects to subscribe to and unsubscribe from notifications when its state changes. The Observable class should provide the following functionalities:

  • subscribe(observer): Adds an observer to the list of observers. An observer is an object with a next method that will be called when the observable emits a new value.
  • unsubscribe(observer): Removes an observer from the list of observers.
  • notify(value): Iterates through all subscribed observers and calls their next method with the provided value.
  • getState(): Returns the current state of the observable.
  • setState(newState): Sets the state of the observable and triggers notifications to all subscribed observers.

The observer object passed to subscribe must have a next method. If it doesn't, the subscribe method should do nothing.

Examples

Example 1:

Input:
observable = new Observable();
observer1 = { next: (value) => console.log("Observer 1:", value) };
observer2 = { next: (value) => console.log("Observer 2:", value) };

observable.subscribe(observer1);
observable.subscribe(observer2);
observable.setState("Initial State");
observable.setState("New State");

Output:
Observer 1: New State
Observer 2: New State

Explanation:
Two observers are subscribed. When `setState` is called with "New State", both observers' `next` methods are called with this value.

Example 2:

Input:
observable = new Observable();
observer1 = { next: (value) => console.log("Observer 1:", value) };
observer2 = { next: (value) => console.log("Observer 2:", value) };

observable.subscribe(observer1);
observable.unsubscribe(observer1);
observable.setState("Updated State");

Output:
(No output)

Explanation:
Observer 1 is subscribed, then immediately unsubscribed.  Therefore, when `setState` is called, only the (non-existent) observer 2 would be notified, and since it's not there, nothing is logged.

Example 3: (Edge Case - Invalid Observer)

Input:
observable = new Observable();
observer1 = {}; // No 'next' method

observable.subscribe(observer1);
observable.setState("State Change");

Output:
(No output)

Explanation:
The observer passed to `subscribe` does not have a `next` method. The `subscribe` method should gracefully handle this and not throw an error or attempt to call a non-existent method.

Constraints

  • The Observable class should be implemented using JavaScript's prototype-based inheritance (no ES6 classes are required, though they are acceptable).
  • The notify method should not throw an error if there are no observers.
  • The setState method should always trigger notifications, even if the new state is the same as the old state.
  • The subscribe method should not modify the observer object passed to it.
  • The unsubscribe method should handle the case where the observer is not currently subscribed. It should not throw an error.

Notes

  • Consider using an array to store the list of observers.
  • The next method of the observer is the only method that needs to be defined. You can add other methods to the observer object as needed.
  • This is a simplified implementation of the Observable pattern. Real-world implementations often include error handling, more sophisticated observer management, and support for different types of events.
  • Focus on the core functionality of subscribing, unsubscribing, and notifying observers. Don't worry about advanced features like error handling or asynchronous notifications.
Loading editor...
javascript