Version v2.2.0 Size 3.0 KB gzip Dependencies Zero dependencies
Why Flux?
Use Flux when an API pushes many values over time and consumers need independent cancellation. Streams describe reusable work; subscriptions own cleanup. Explicit queue capacity keeps async iteration from silently growing memory.
ts
// Before
const controller = new AbortController();
const render = (value: string) => console.log(value);
const handler = (event: Event) => render((event.target as HTMLInputElement).value);
input.addEventListener('input', handler);
setTimeout(() => controller.abort(), 5_000);
// After
import { fromEvent, map, pipe, takeUntil } from '@vielzeug/flux';
const updates = pipe(
fromEvent<InputEvent>(input, 'input'),
map((event) => (event.target as HTMLInputElement).value),
takeUntil(controller.signal),
);
updates.subscribe({ error: console.error, next: render });| Feature | Flux | RxJS | TC39 Observable |
|---|---|---|---|
| Bundle size | 3.0 KB | Varies by imported operators | Native proposal / polyfill |
| Runtime dependencies | |||
| Subscription-owned cancellation | |||
| Explicit async queue policy | Operator-dependent | No standard policy | |
| Vielzeug adapters | Ripple, Courier, Herald, Pulse | Manual adapters | Manual adapters |
Use Flux when you need a small TypeScript stream primitive, explicit cancellation, and first-party Vielzeug adapters.
Consider RxJS when you need its larger operator catalog or third-party Observable integrations.
Installation
sh
pnpm add @vielzeug/fluxsh
npm install @vielzeug/fluxsh
yarn add @vielzeug/fluxQuick Start
ts
import { toArray, interval, map, pipe, take } from '@vielzeug/flux';
const firstThree = pipe(
interval({ every: 100 }),
map((value) => value * 2),
take(3),
);
try {
console.log(await toArray(firstThree, { maxItems: 3 })); // [0, 2, 4]
} catch (reason) {
console.error('Stream failed', reason);
}Features
stream()— define cold reusable work with one teardown functionpipe()— compose any number of typed operatorsSubscription— own cancellation throughunsubscribe()orAbortSignalcreateChannel()— mutable multicast state with bounded replaytoAsyncIterable()— explicit capacity and overflow policy for pull consumersretry()— retry failures with optional backofffromSignal()/toSignal()— bridge Ripple signalsfromQuery()— adapt Courier query state