toAsync
Lifts a plain Iterable — of values or Futures — into an FxAsyncIterable, the entry point to FxDart's async pipeline.
Lecture
Every async pipeline in FxDart starts with toAsync. It takes
a plain Iterable<FutureOr<T>> — a list of plain
values, a list of Futures, or a mix — and wraps it in an
FxAsyncIterable, the type every *Async operator
and the FxAsync chain understand. Whenever an element turns
out to be a Future, it's awaited automatically as it's pulled.
FxAsyncIterable is pull-based: nothing runs
until a terminal (toListAsync, eachAsync, the
FxAsync chain's .toList(), …) calls
next() on it, one step at a time — exactly like a plain
Iterable, just asynchronous. This is a deliberate departure
from Dart's Stream, which is push-based: once a
stream starts emitting, it decides the pace, and there's no way for a
downstream consumer to tell it "evaluate 3 of these at once." FxDart's
next([Concurrent? concurrent]) protocol adds exactly that
back-channel — a downstream operator like concurrent(n) can
pass a marker upstream through every pull, asking the source to
run n items in parallel. Streams have no equivalent hook, which
is the whole reason FxDart defines its own async iterable instead of
building on Stream.
Use the top-level toAsync(iterable) for a raw
Iterable<FutureOr<T>>, or the chain method
fx(iterable).toAsync() to switch an existing Fx
chain into its FxAsync counterpart. Both are lazy: building
the pipeline does nothing until something pulls.
Demo 1 · Values, Futures, and the chain form
toAsync accepts plain values, Futures, or a mix of both —
and the chain form does the same thing from an existing Fx:
Demo 2 · Why the pull-based model matters
In Dart, a Future starts running the instant it's created —
not when it's awaited. So three Futures built eagerly in a list literal
are already racing before toAsync ever touches them. Contrast
that with mapAsync (or chain .map), which creates
one new Future per element only when it's pulled — lazily, one at
a time, unless you add concurrent(n):
Method spelling
xs.fxAsync is this function as a getter. It returns an
FxAsync rather than a bare FxAsyncIterable, so
the chain is ready to continue — and it resolves the futures, which
xs.fx does not.
await responses.fxAsync.map(parse).concurrent(4).toList();
// responses.fx would be an Fx<Future<T>> — a chain over the
// futures rather than their values.
The name carries fx on purpose. toAsync is a
general enough phrase that on a bare Iterable it would say
nothing about which library it enters; the getter spellings are collected
in fx.
Try it yourself
Exercise: filter the list below so only passing scores (>= 60) make it into the result.
*Async naming convention — mapAsync, filterAsync, … ·
Stream bridges — fromStream, fxStream, toStream ·
concurrent — the back-channel in action ·
delay & sleep — building async demos