Postboy Help

Composing Responses from Multiple Sources

Sometimes a single view needs data from several independent backend calls or needs to chain callback requests sequentially. Postboy callback messages compose naturally with RxJS operators, allowing you to build complex data‑fetching pipelines while keeping each callback typed and isolated.

1. Sequential calls (chaining)

When one callback’s result is needed to fire the next, use mergeMap (or switchMap) to chain.

import {mergeMap} from 'rxjs/operators'; import {GetUserQuery} from './messages/queries/get-user.query'; import {GetOrdersQuery} from './messages/queries/get-orders.query'; // Suppose we need the user’s email to fetch their orders. this.postboy.fireCallback(new GetUserQuery('123')).pipe( mergeMap((user) => { if (!user) return of(null); return this.postboy.fireCallback(new GetOrdersQuery(user.email)); }) ).subscribe((orders) => { console.log('Orders loaded:', orders); });

2. Parallel calls (independent sources)

When the requests are independent, gather them in parallel with forkJoin. Every callback is fired once and all results arrive together.

import {forkJoin} from 'rxjs'; import {GetUserProfileQuery} from './messages/queries/get-user-profile.query'; import {GetUserSettingsQuery} from './messages/queries/get-user-settings.query'; const profile$ = this.postboy.fireCallback(new GetUserProfileQuery('123')); const settings$ = this.postboy.fireCallback(new GetUserSettingsQuery('123')); forkJoin([profile$, settings$]).subscribe(([profile, settings]) => { if (profile && settings) { console.log('Dashboard ready'); } else { console.log('Some data is missing'); } });

3. Mixing sequential and parallel

A typical pattern: get a master record, then fetch several dependent child collections in parallel.

this.postboy.fireCallback(new GetCustomerQuery(customerId)).pipe( switchMap((customer) => { if (!customer) return of(null); return forkJoin({ customer: of(customer), orders: this.postboy.fireCallback(new GetOrdersQuery(customer.id)), invoices: this.postboy.fireCallback(new GetInvoicesQuery(customer.id)), }); }) ).subscribe((result) => { if (result) { console.log('Customer details', result.customer); console.log('Orders', result.orders); console.log('Invoices', result.invoices); } });

4. Combining multiple results into a single view model

You can map the aggregated result into a dedicated view model before updating the UI.

interface DashboardVM { user: User; orders: Order[]; notifications: Notification[]; } forkJoin({ user: this.postboy.fireCallback(new GetUserQuery(userId)), orders: this.postboy.fireCallback(new GetOrdersQuery(userId)), notifications: this.postboy.fireCallback(new GetNotificationsQuery(userId)), }).pipe( map(({user, orders, notifications}) => ({ user: user ?? null, orders: orders ?? [], notifications: notifications ?? [], } as DashboardVM)) ).subscribe((vm) => { this.dashboard = vm; });

Key points

  • Every fireCallback returns a typed Observable<T>. You can combine them as you would any other RxJS stream.

  • Use mergeMap/switchMap for sequential calls that depend on the previous result.

  • Use forkJoin or combineLatest for parallel calls that are independent of each other.

  • Remember that a callback always expects msg.finish(result) to be called; if some handler never finishes, the composition will hang.

  • All the composition logic stays inside the sender; handlers remain simple, single‑purpose units.

24 апреля 2026