Core Concepts

Async operations

Mix Promise, Observable, and expression values with sync values in one expression.

For runtime internals, see the advanced async operations page.

What it means

In rs-x, async and sync values work the same way inside expressions. You can mix both in one expression, and updates from each value type flow through the same reactive pipeline.

Practical value

You avoid manual await/subscribe glue code per dependency. For example, with { a: 10, b: Promise.resolve(20) } you can bind "a + b" directly.

Key points

Promise example

Bind directly to a Promise field and treat it like a normal value in the expression.

import { InjectionContainer } from '@rs-x/core';
import { rsx, RsXExpressionParserModule } from '@rs-x/expression-parser';

await InjectionContainer.load(RsXExpressionParserModule);

const model = {
  a: 10,
  b: Promise.resolve(20),
};

const sum = rsx<number>('a + b')(model);
const sumChangedSubscription = sum.changed.subscribe(() => {
  console.log('sum:', sum.value);
});

const randomInt = (min: number, max: number): number =>
  Math.floor(Math.random() * (max - min + 1)) + min;

const aInterval = setInterval(() => {
  model.a = randomInt(5, 25);
}, 2000);

Observable (RxJS) example

Bind directly to an observable source and react to next(...) emissions.

import { InjectionContainer } from '@rs-x/core';
import { rsx, RsXExpressionParserModule } from '@rs-x/expression-parser';
import { BehaviorSubject } from 'rxjs';

await InjectionContainer.load(RsXExpressionParserModule);

const model = {
  a: 10,
  b: new BehaviorSubject(20),
};

const sum = rsx<number>('a + b')(model);
const sumChangedSubscription = sum.changed.subscribe(() => {
  console.log('sum:', sum.value);
});

const randomInt = (min: number, max: number): number =>
  Math.floor(Math.random() * (max - min + 1)) + min;

const aInterval = setInterval(() => {
  model.a = randomInt(5, 25);
}, 2000);

rsx expression value example

Bind one expression as a value inside another expression, including async inner dependencies.

import { InjectionContainer } from '@rs-x/core';
import { rsx, RsXExpressionParserModule } from '@rs-x/expression-parser';

await InjectionContainer.load(RsXExpressionParserModule);

const partialModel = {
  base: 10,
  bonus: Promise.resolve(20),
};

const partial = rsx<number>('base + bonus')(partialModel);
const totalModel = {
  a: 5,
  partial,
};
const total = rsx<number>('a + partial')(totalModel);

const totalChangedSubscription = total.changed.subscribe(() => {
  console.log('total:', total.value);
});

const randomInt = (min: number, max: number): number =>