Broadcast
Event bus for emitting and listening to events across browser contexts using the BroadcastChannel API.
Usage
import { Broadcast, Payload } from '@accelint/bus';
type AppEvents = Payload<'user:login', { userId: string }>;
const bus = Broadcast.getInstance<AppEvents>();
// Listen for events
bus.on('user:login', (event) => {
console.log('User logged in:', event.payload.userId);
});
// Emit events
bus.emit('user:login', { userId: '123' });Reference
Type Parameters
Events- Union type of all event payloads. Should be a union ofPayload<type, data>types.
Constructor
constructor(config?: BroadcastConfig)Creates a new Broadcast instance. For most cases, use getInstance() instead to access the singleton.
Parameters:
| Parameter | Type | Description |
|---|---|---|
config | BroadcastConfig | Optional configuration object |
config.channelName | string | Name of the BroadcastChannel (default: '@accelint/bus') |
Static Methods
getInstance
static getInstance<T extends BasicPayload>(config?: BroadcastConfig): Broadcast<T>Returns the singleton Broadcast instance. Creates the instance on first call.
Good to know: Broadcast uses a singleton pattern. Multiple calls to
getInstance()return the same instance, ensuring events are shared across your entire application.
Event Methods
on
on<Type extends Events['type']>(
type: Type,
callback: (data: ExtractEvent<Events, Type>) => void
): () => voidRegisters a callback for the specified event type. Returns an unsubscribe function.
Parameters:
| Parameter | Type | Description |
|---|---|---|
type | Type extends Events['type'] | The event type to listen for |
callback | (data: ExtractEvent<Events, Type>) => void | Function called when event is received |
Returns: Unsubscribe function to remove the listener
once
once<Type extends Events['type']>(
type: Type,
callback: (data: ExtractEvent<Events, Type>) => void
): () => voidLike on, but the callback is automatically removed after being invoked once.
off
off<Type extends Events['type']>(
type: Type,
callback: (data: ExtractEvent<Events, Type>) => void
): voidUnregisters a specific callback for an event type.
emit
emit<Type extends Events['type']>(
type: Type,
payload: Data,
options?: EmitOptions
): voidEmits an event to all listening contexts.
Parameters:
| Parameter | Type | Description |
|---|---|---|
type | Type extends Events['type'] | The event type |
payload | Data | Event payload (must be serializable via structured clone algorithm) |
options | EmitOptions | Optional delivery options |
options.target | 'self' | 'others' | 'all' | UniqueId | Target delivery scope (default: 'self') |
Configuration Methods
setEventEmitOptions
setEventEmitOptions(type: Events['type'], options: EmitOptions | null): voidSets default emit options for a specific event type. These options are merged with global and local options (global < event < local precedence).
setEventsEmitOptions
setEventsEmitOptions(events: Map<Events['type'], EmitOptions | null>): voidSets emit options for multiple events at once.
setGlobalEmitOptions
setGlobalEmitOptions(options: EmitOptions | null): voidSets default emit options for all events. Lowest precedence in the merge hierarchy.
Management Methods
deleteEvent
deleteEvent(type: Events['type']): voidRemoves all listeners and configuration for a specific event type.
destroy
destroy(): voidCloses the BroadcastChannel and cleans up all listeners. After calling this, the instance is no longer usable.
ping
ping(): voidSends a ping to discover other Broadcast instances. Updates the connected property with responding instance IDs.
Good to know: Due to the event-driven nature of ping/echo, this is neither synchronous nor awaitable. Listen for ping/echo events and update UI reactively to reflect the current state of the
connectedproperty.
Properties
id
readonly id: UniqueIdRead-only unique identifier for this Broadcast instance.
connected
readonly connected: ReadonlySet<UniqueId>Read-only set of IDs for other Broadcast instances currently communicating with this one. Updated when instances ping/echo or disconnect.
Examples
Example: Basic pub/sub
import { Broadcast, Payload } from '@accelint/bus';
type Events = Payload<'message', { text: string }>;
const bus = Broadcast.getInstance<Events>();
// Subscribe
const unsubscribe = bus.on('message', (event) => {
console.log(event.payload.text);
});
// Publish
bus.emit('message', { text: 'Hello!' });
// Later: cleanup
unsubscribe();Example: One-time listener
import { Broadcast, Payload } from '@accelint/bus';
type Events = Payload<'init:complete'>;
const bus = Broadcast.getInstance<Events>();
bus.once('init:complete', () => {
console.log('App initialized'); // Only fires once
});
bus.emit('init:complete');
bus.emit('init:complete'); // Callback not calledExample: Targeting specific instances
import { Broadcast, Payload } from '@accelint/bus';
type Events = Payload<'sync', { data: unknown }>;
const bus = Broadcast.getInstance<Events>();
// Emit only to self (default)
bus.emit('sync', { data: {} });
// Emit to all including self
bus.emit('sync', { data: {} }, { target: 'all' });
// Emit to all others (not self)
bus.emit('sync', { data: {} }, { target: 'others' });
// Emit to specific instance by ID
const targetId = '...'; // Another bus instance ID
bus.emit('sync', { data: {} }, { target: targetId });Example: Discovering connected instances
import { Broadcast } from '@accelint/bus';
const bus = Broadcast.getInstance();
// Request discovery
bus.ping();
// Listen for connection events
bus.on('__PING__', ({ source }) => {
console.log(`Discovered instance: ${source}`);
});
bus.on('__ECHO__', ({ source }) => {
console.log(`Connected to instance: ${source}`);
});
// Check connected instances (after async responses arrive)
setTimeout(() => {
console.log(`Connected instances: ${bus.connected.size}`);
for (const id of bus.connected) {
console.log(`- ${id}`);
}
}, 100);Example: Event-specific options
import { Broadcast, Payload } from '@accelint/bus';
type Events =
| Payload<'local', { data: string }>
| Payload<'broadcast', { data: string }>;
const bus = Broadcast.getInstance<Events>();
// Configure 'local' to only emit to self
bus.setEventEmitOptions('local', { target: 'self' });
// Configure 'broadcast' to emit to all including self
bus.setEventEmitOptions('broadcast', { target: 'all' });
// Now all 'local' emits stay local
bus.emit('local', { data: 'private' }); // Only this instance receives
// 'broadcast' emits to all instances
bus.emit('broadcast', { data: 'public' }); // All instances receiveExample: Cleanup on destroy
import { Broadcast } from '@accelint/bus';
const bus = Broadcast.getInstance();
bus.on('some-event', () => {
// Handler logic
});
// Later: clean up completely
bus.destroy();
// After destroy, bus is unusable
// Calling getInstance() will create a new instanceGood to know: Events emitted via Broadcast are delivered using the structured clone algorithm. This means payloads must be serializable—functions, DOM nodes, and symbols cannot be sent.
Related
- useBus - React hook wrapper for Broadcast
- useEmit - React hook for emitting events
- useOn - React hook for listening to events
- Payload - Type helper for defining events
- BroadcastChannel API - Underlying browser API
Overview
The @accelint/bus package provides a type-safe event bus for emitting and listening to events across browser contexts (tabs, windows, iframes). It's built on top of the native BroadcastChannel API and includes React hooks for seamless integration.
React Hooks
React hooks for type-safe event bus integration including useBus, useEmit, useOn, and useOnce.