Postboy Help

Events

An event is a one-way broadcast. A publisher fires a message and moves on; any number of subscribers react independently, and nothing is returned. Events extend PostboyGenericMessage and use the fire, sub, and once verbs. When the sender needs a result, use a callback message instead — see Callbacks.

When to use events

Use events for domain notifications, UI broadcasts, and state-change signals with zero or many listeners. Do not use them for request/response (use callbacks) or when a value is needed synchronously (use executors).

Define an event

import {PostboyGenericMessage} from '@artstesh/postboy'; export class StockUpdatedEvent extends PostboyGenericMessage { static readonly ID = 'shop.stock.updated'; constructor(public readonly productId: string, public readonly newStatus: string) { super(); } }

Register the event type

The idiomatic home for registration is a registrator:

import {PostboyAbstractRegistrator} from '@artstesh/postboy'; class ShopRegistrator extends PostboyAbstractRegistrator { protected _up(): void { this.recordSubject(StockUpdatedEvent); // plain Subject } } new ShopRegistrator(postboy, 'shop').up(); // registrations become active

Or connect the subject directly:

import {ConnectMessage} from '@artstesh/postboy'; import {Subject} from 'rxjs'; postboy.exec(new ConnectMessage(StockUpdatedEvent, new Subject<StockUpdatedEvent>()));

Publish with fire

postboy.fire(new StockUpdatedEvent('P-42', 'out-of-stock'));

fire returns void. A registered event with no subscribers is discarded silently; firing an unregistered ID throws.

Subscribe with sub and once

// react to every occurrence postboy.sub(StockUpdatedEvent).subscribe((msg) => { console.log(msg.productId, msg.newStatus); }); // react to the next occurrence only, then complete automatically postboy.once(StockUpdatedEvent).subscribe((msg) => { console.log(msg.productId, msg.newStatus); });

Subject flavors

The registration flavor decides what new subscribers see.

Plain subject (recordSubject, or new Subject() with ConnectMessage) — subscribers only receive messages fired after they subscribed.

Replay (recordReplay) — new subscribers immediately receive the latest fired message:

protected _up(): void { this.recordReplay(StockUpdatedEvent); // buffer size 1 by default }

Behavior (recordBehavior) — the event models state; every subscriber receives the current message, and the initial value is a message instance:

export class ThemeEvent extends PostboyGenericMessage { static readonly ID = 'ui.theme'; constructor(public readonly payload: { mode: 'light' | 'dark' }) { super(); } } protected _up(): void { this.recordBehavior(ThemeEvent, new ThemeEvent({mode: 'dark'})); }

Subscription hygiene

  • sub returns an Observable<T>, not a Subject. Never call .next() on it — publish with fire.

  • Keep the Subscription returned by .subscribe(...) and unsubscribe on teardown; once completes by itself after the first message.

  • Subscribe after registration. sub on an unregistered type returns a cold observable that never emits.

Pitfalls

  • Calling .next() on the result of sub — it is an Observable; publishing goes through fire.

  • Firing before registration — the bus throws for unregistered IDs.

  • Re-registering the same type ad hoc — the second registration silently overwrites the first; group registrations in one registrator.

  • Expecting replay semantics from a plain subject — late subscribers miss earlier messages; use recordReplay.

Next steps

07 September 2026