race

The first candidate to emit wins: its whole stream is mirrored, and every other candidate is cancelled on the spot.

static FxEvents<T> FxEvents.race<T>(Iterable<Stream<T>> candidates)

Lecture

Ask the cache and the network at the same time; take whichever answers first. Try three download mirrors; keep the fastest. FxEvents.race(candidates) subscribes to every candidate at once, and the first event anywhere decides it: that event is delivered, and every losing candidate is cancelled immediately — not muted, cancelled. Their sockets close, their work stops, their events never happen.

Be precise about what wins: the first event anywhere picks the winner, and from then on the race mirrors the winning stream in full — every later event it produces flows through, and the race closes when the winner closes. An error can win too: a fast broken endpoint beats a slow healthy one, which is exactly the honest behavior — you asked who answers first, and "it failed" is an answer. Guard slow-and-flaky fields with timeout/retry on each candidate before racing them.

Candidates that close without ever emitting drop out silently; if all of them do — or the candidate list is empty — the race closes empty. Note the direction of cancellation versus its neighbor: switchMap cancels the older of successive streams, race cancels the slower of simultaneous ones. fxdart events layer, after Rx's race/amb.

Demo 1 · Cache vs network, losers cancelled

Demo 2 · Errors can win, empty candidates drop out

Try it yourself

Exercise: fastest of three mirrors.

Related: switchMap — cancelling the older instead of the slower · timeout — bound each candidate before the race · fxEventsFxEvents.merge, when you want everyone's events, not a winner