Core Concepts

Batching changes

Group multiple model updates and emit one final expression change.

What it means

rs-x collects updates first and publishes the final value at the end of a change cycle. You can pause publishing with suspend() and release all pending work with continue().

Practical value

This keeps change events predictable: fewer noisy intermediate values, less duplicate work, and clearer logs for subscribers.

Key points

What this example proves

The example intentionally flushes between unbatched writes, so each write gets its own commit and you can see multiple emissions.

In the batched part, the same writes run while suspended. continue() then flushes once, so subscribers see one final emission.

Why unbatched can still look like one emission

If several writes happen immediately after each other in one synchronous turn, rs-x can still publish one final value.

That is expected behavior. It means the system coalesced those writes before the commit boundary.

When to use suspend and continue

Use it for multi-step updates where partial states should stay private until everything is ready.

Typical cases are import pipelines, validation-and-fix passes, or grouped recalculations where you only care about the final result.

Example

import { emptyFunction, InjectionContainer, WaitForEvent } from '@rs-x/core';
import {
  type IExpressionChangeTransactionManager,
  rsx,
  RsXExpressionParserInjectionTokens,
  RsXExpressionParserModule,
} from '@rs-x/expression-parser';

await InjectionContainer.load(RsXExpressionParserModule);

const tx = InjectionContainer.get<IExpressionChangeTransactionManager>(
  RsXExpressionParserInjectionTokens.IExpressionChangeTransactionManager,
);

const model = {
  subtotal: 100,
  shipping: 15,
  discount: 5,
};

const totalExpression = rsx<number>('subtotal + shipping - discount')(model);