Hone logo
Hone
Problems

Vue Event Bus Implementation with TypeScript

An event bus provides a simple way for components to communicate with each other without direct parent-child relationships. This challenge asks you to implement a basic event bus in Vue using TypeScript, enabling components to publish and subscribe to events across the application. This is particularly useful for loosely coupled components that need to share data or trigger actions.

Problem Description

You need to create a VueEventBus class in TypeScript that provides the following functionality:

  • $on(event: string, callback: (payload?: any) => void): void: Subscribes a callback function to a specific event. The callback function should receive an optional payload.
  • $off(event: string, callback: (payload?: any) => void): void: Unsubscribes a specific callback function from a specific event. This is crucial to prevent memory leaks.
  • $emit(event: string, payload?: any): void: Publishes an event with an optional payload. All subscribed callbacks for that event will be executed with the provided payload.

The event bus should internally manage a list of subscriptions for each event. When $emit is called, it should iterate through the subscriptions for the specified event and execute each callback. When $off is called, it should remove the specified callback from the list of subscriptions for the event.

Key Requirements:

  • The implementation must be in TypeScript.
  • The event bus should be reusable across different Vue applications.
  • The $off method must correctly remove the specified callback function, not just the event name.
  • The event bus should handle multiple subscriptions to the same event.
  • The event bus should handle events with and without payloads.

Expected Behavior:

  • Subscribing to an event should add the callback to the list of listeners for that event.
  • Emitting an event should execute all subscribed callbacks with the provided payload (or undefined if no payload is provided).
  • Unsubscribing a callback should remove it from the list of listeners for the event.
  • Attempting to emit an event after all subscribers have unsubscribed should have no effect.
  • Attempting to unsubscribe a callback that was never subscribed should have no effect.

Edge Cases to Consider:

  • What happens if $on is called with an event name that doesn't exist? (Should create a new subscription list)
  • What happens if $off is called with an event name that doesn't exist? (Should have no effect)
  • What happens if $off is called with a callback that wasn't originally subscribed? (Should have no effect)
  • How to prevent memory leaks by ensuring callbacks are properly unsubscribed when components are destroyed. (While not explicitly required to implement component destruction handling, consider this in your design).

Examples

Example 1:

Input:
  - eventBus.$on('myEvent', (payload) => { console.log('Received:', payload); });
  - eventBus.$emit('myEvent', { message: 'Hello!' });
Output:
  - console.log('Received: { message: "Hello!" }')
Explanation: The callback function is executed with the payload { message: "Hello!" }.

Example 2:

Input:
  - eventBus.$on('anotherEvent', (payload) => { console.log('Another event:', payload); });
  - eventBus.$on('anotherEvent', (payload) => { console.log('Another event (again):', payload); });
  - eventBus.$emit('anotherEvent', 'Some data');
  - eventBus.$off('anotherEvent', (payload) => { console.log('Another event (again):', payload); });
  - eventBus.$emit('anotherEvent', 'More data');
Output:
  - console.log('Another event: Some data')
  - console.log('Another event (again): Some data')
  - console.log('Another event: More data')
Explanation:  Two callbacks are subscribed to 'anotherEvent'. The first emit executes both.  The second emit executes only the first callback after the second is unsubscribed.

Example 3: (Edge Case)

Input:
  - eventBus.$on('nonExistentEvent', (payload) => { console.log('This should not be called'); });
  - eventBus.$emit('anotherEvent', 'Some data');
Output:
  - No output to console.
Explanation:  Emitting an event that no one is listening to has no effect.

Constraints

  • The implementation must be written in TypeScript.
  • The event bus should be lightweight and efficient.
  • The code should be well-documented and easy to understand.
  • The event bus should not rely on any external libraries beyond standard TypeScript features.
  • The $on and $off methods should be able to handle callbacks that are defined as arrow functions.

Notes

  • Consider using a Map or Object to store event subscriptions.
  • Pay close attention to the callback function identity when unsubscribing. You need to remove the exact function reference, not just a function with the same code.
  • Think about how to handle potential errors or unexpected input.
  • While not required, consider how this event bus could be extended to support wildcards or namespaces for event names.
Loading editor...
typescript