Hone logo
Hone
Problems

Event Bus with Wildcard Subscriptions in JavaScript

Event buses provide a centralized mechanism for components to communicate without direct dependencies. This challenge asks you to implement a JavaScript event bus that supports both specific event subscriptions and wildcard subscriptions, allowing subscribers to listen for events matching a pattern. This is useful for decoupling components and creating flexible, reactive systems.

Problem Description

You are tasked with creating a JavaScript class called EventBus that manages event subscriptions and dispatches events. The EventBus should provide the following functionalities:

  • subscribe(event, callback): Registers a callback function to be executed when the event is dispatched. The event can be a string representing a specific event name or a string with a wildcard character *. Wildcards match any event name that starts with the specified prefix. For example, 'user.*' would match 'user.created', 'user.updated', and 'user.deleted'.
  • unsubscribe(event, callback): Removes the specified callback function from the list of subscribers for the given event. If the event is a wildcard, it removes all callbacks subscribed to that wildcard.
  • dispatch(event, data): Triggers all registered callbacks for the given event. The data argument is passed to each callback function. If the event is a wildcard, it iterates through all events matching the wildcard pattern and executes the corresponding callbacks.

Key Requirements:

  • The EventBus should handle multiple subscribers for the same event.
  • The unsubscribe method should correctly remove the specified callback.
  • Wildcard subscriptions should correctly match events based on the prefix.
  • The dispatch method should pass the provided data to the callbacks.
  • The implementation should be efficient and avoid unnecessary iterations.

Expected Behavior:

  • Subscribing to an event should add the callback to the appropriate subscriber list.
  • Unsubscribing should remove the callback.
  • Dispatching an event should execute all matching callbacks with the provided data.
  • Dispatching an event with no subscribers should not throw an error.
  • Unsubscribing a callback that wasn't subscribed should not throw an error.

Edge Cases to Consider:

  • Empty event names.
  • Callbacks that are not functions.
  • Wildcards at the end of the event name (e.g., *).
  • Multiple wildcards in the event name (e.g., user.*.*). (For simplicity, assume only one wildcard is used.)
  • Unsubscribing a callback that doesn't exist.
  • Dispatching an event with no data.

Examples

Example 1:

Input:
eventBus.subscribe('user.created', (data) => console.log('User created:', data));
eventBus.dispatch('user.created', { id: 1, name: 'Alice' });

Output:
User created: { id: 1, name: 'Alice' }

Explanation: The callback subscribed to 'user.created' is executed with the provided data.

Example 2:

Input:
eventBus.subscribe('user.*', (data) => console.log('User event:', data));
eventBus.dispatch('user.updated', { id: 1, name: 'Bob' });
eventBus.unsubscribe('user.*', (data) => console.log('User event:', data));
eventBus.dispatch('user.deleted', { id: 2 });

Output:
User event: { id: 1, name: 'Bob' }

Explanation: The wildcard subscription 'user.*' matches 'user.updated', executing the callback. The callback is then unsubscribed, so 'user.deleted' does not trigger it.

Example 3:

Input:
eventBus.subscribe('system.error', (data) => console.log('System error:', data));
eventBus.dispatch('other.event', { message: 'Some message' });
eventBus.dispatch('system.error', { code: 500, message: 'Internal Server Error' });

Output:
System error: { code: 500, message: 'Internal Server Error' }

Explanation: Only the callback subscribed to 'system.error' is executed, as 'other.event' does not match any subscription.

Constraints

  • The event string can be up to 255 characters long.
  • The callback function must be a function.
  • The data passed to the callback can be any JavaScript value.
  • The implementation should have a time complexity of O(n) for dispatch in the worst case, where n is the number of matching subscribers. subscribe and unsubscribe should ideally be O(1) or O(n) where n is the number of subscribers for a specific event/wildcard.

Notes

  • Consider using a data structure (e.g., a Map or object) to store subscriptions efficiently.
  • The wildcard matching should be based on string prefix comparison.
  • Think about how to handle errors gracefully, such as when a callback is not a function.
  • Focus on creating a clean, readable, and well-documented implementation.
  • You do not need to worry about thread safety or asynchronous operations.
Loading editor...
javascript