Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Events

The Bus is a pub/sub event bus with support for string events, class-based events, wildcard listeners, and deferred dispatch via queuing.

Register it by including EventsProvider in your providers:

import { Application, EventsProvider } from "@raubjo/architect-core"

Application.configure()
  .withProviders([new EventsProvider()])
  .run()

Listening

import { Event } from "@raubjo/architect-core/support/facades"

const off = Event.listen("user.created", (payload) => {
  console.log(payload)
})

// Stop listening
off()

Dispatching

await Event.dispatch("user.created", { id: 42, name: "Alice" })

// Alias
await Event.fire("user.created", { id: 42 })

Listen once

Event.once("app.ready", () => {
  console.log("App is ready")
})

Wildcard listeners

Event.listen("*", (eventName, data) => {
  console.log(eventName, data)
})

Class-based events

Define event classes for type safety:

class UserCreated {
  constructor(public readonly id: number, public readonly name: string) {}
}

Event.listen(UserCreated, (event) => {
  console.log(event.id, event.name)
})

await Event.dispatch(new UserCreated(42, "Alice"))

Add a static label to control the event name (minification-safe):

class UserCreated {
  static readonly label = "user.created"
  constructor(public readonly id: number) {}
}

Dispatchable mixin

Make a class dispatch itself:

import { Dispatchable } from "@raubjo/architect-core"

class UserCreated extends Dispatchable {
  constructor(public readonly id: number) {}
}

// Dispatches via the Event facade
await UserCreated.dispatch(new UserCreated(42))

Subscribers

Group related listeners into a subscriber class:

import { type EventSubscriber, type Bus } from "@raubjo/architect-core"

class UserSubscriber implements EventSubscriber {
  subscribe(bus: Bus) {
    return {
      "user.created": this.onUserCreated,
      "user.deleted": this.onUserDeleted,
    }
  }

  onUserCreated(event: unknown) { /* ... */ }
  onUserDeleted(event: unknown) { /* ... */ }
}

Event.subscribe(new UserSubscriber())
// or pass the class — subscriber will be instantiated automatically
Event.subscribe(UserSubscriber)

Listening for the first truthy response

const result = await Event.until("form.validate", formData)
// Returns the first non-null, non-false listener return value

Queued events

Push an event to a queue without dispatching immediately. Flush later to dispatch all queued payloads in order:

Event.push("analytics.track", { event: "page_view", url: "/home" })
Event.push("analytics.track", { event: "page_view", url: "/about" })

// Later, when the analytics service is ready:
await Event.flush("analytics.track")

Using Bus directly

import { Bus } from "@raubjo/architect-core"

boot({ container }) {
  const bus = container.make(Bus)
  bus.listen("order.placed", this.handleOrder)
}