Hone logo
Hone
Problems

React Pub-Sub Implementation

This challenge asks you to build a simple publish-subscribe (pub-sub) system within a React application using TypeScript. Pub-sub is a messaging pattern where publishers emit events, and subscribers listen for those events, enabling decoupled communication between components. Implementing this in React allows for efficient data sharing and component interaction without direct dependencies.

Problem Description

You need to create a PubSub class that manages event subscriptions and dispatches events. This class should provide the following functionalities:

  • subscribe(event: string, callback: (data: any) => void): () => void: This method allows subscribers to register a callback function for a specific event. It should return an unsubscribe function that, when called, removes the subscriber from the event's listener list.
  • publish(event: string, data: any): This method publishes an event with associated data. It should iterate through all subscribers for the given event and execute their callback functions, passing the data as an argument.
  • removeEvent(event: string): This method removes all subscriptions for a given event.

The PubSub class should maintain an internal data structure (e.g., a Map or object) to store event subscriptions. The unsubscribe function returned by subscribe must correctly remove the callback from the subscription list.

Expected Behavior:

  • Subscribers should only receive events they have explicitly subscribed to.
  • Multiple subscribers can listen to the same event.
  • Unsubscribing a subscriber should prevent it from receiving further events.
  • Publishing an event with no subscribers should not cause any errors.
  • removeEvent should remove all listeners for a given event.

Edge Cases to Consider:

  • Subscribing to an event with a callback that throws an error. The error should not crash the entire pub-sub system; it should only prevent that specific callback from being executed again for that event.
  • Publishing an event with no data.
  • Attempting to unsubscribe a subscriber that has already been unsubscribed.
  • Calling publish with an event name that has no subscribers.
  • Calling removeEvent with an event name that has no subscribers.

Examples

Example 1:

Input:
PubSub instance: pubSub
pubSub.subscribe('user.login', (data) => console.log('User logged in:', data));
pubSub.publish('user.login', { username: 'john.doe' });

Output:
console.log('User logged in: { username: "john.doe" }')

Explanation: The subscriber receives the data associated with the 'user.login' event.

Example 2:

Input:
PubSub instance: pubSub
const unsubscribe = pubSub.subscribe('data.update', (data) => console.log('Data updated:', data));
pubSub.publish('data.update', { value: 123 });
unsubscribe();
pubSub.publish('data.update', { value: 456 });

Output:
console.log('Data updated: { value: 123 }') // Only this log appears

Explanation: The subscriber is unsubscribed before the second publish, so it doesn't receive the second event.

Example 3: (Edge Case - Error Handling)

Input:
PubSub instance: pubSub
pubSub.subscribe('error.event', () => { throw new Error('Callback failed!'); });
pubSub.publish('error.event', {});

Output:
No error should crash the PubSub instance.  The callback should be removed from the listener list for 'error.event'. Subsequent publishes to 'error.event' should not trigger the faulty callback.

Explanation: The error within the callback should not prevent other subscribers (if any) from receiving the event, nor should it crash the PubSub instance.

Constraints

  • The PubSub class should be implemented in TypeScript.
  • The subscribe method must return a function that, when called, removes the subscriber.
  • The publish method should not throw errors if there are no subscribers for a given event.
  • The removeEvent method should not throw errors if the event doesn't exist.
  • The solution should be reasonably performant for a small number of subscribers (up to 100 per event). Optimization for extremely high subscriber counts is not required.
  • The code should be well-structured and easy to understand.

Notes

  • Consider using a Map or a plain JavaScript object to store event subscriptions.
  • Think about how to handle errors that might occur within subscriber callbacks.
  • The focus is on the core pub-sub functionality; you don't need to worry about React component integration or complex error handling beyond preventing a single callback error from crashing the system.
  • The data parameter in publish can be of any type.
  • The callback function in subscribe should accept a single argument of type any, representing the data passed to publish.
Loading editor...
typescript