Throttle the refresh button
Requirement
A user hammers the refresh button: taps at 0/50/100/400/450/800 ms. Let at most one refresh through per 300 ms window, taking the first tap in each window — so exactly three refreshes fire (taps 0, 3 and 5). Print which taps got through after the stream closes. The tap schedule is simulated in the code; both versions must print the lines shown under Expected output.
Expected output
refresh fired on tap 0 refresh fired on tap 3 refresh fired on tap 5 taps: 6, refreshes: 3
Side by side
RxDart
FxDart
Why they differ
They don't. Throttling is rate-limiting arrivals in
time — a property of when events happen, not of the values — and
both panels collapse the requirement into one operator on the tap
stream. RxDart's throttleTime(300ms) and fxdart's
fxEvents(...).throttle(300ms) implement the same
leading-edge window (first tap emits and opens the window, the rest of
the burst is swallowed; a trailing edge is a flag away on either
side), with subscription, window bookkeeping and completion all inside
the operator.
fxdart deliberately absorbs the Rx approach
for the push side: fxEvents is a wrapper chain over plain
Streams — not an extension, so it coexists with any
stream library without a single member conflict. RxDart's operator
catalog remains far larger than fxdart's events layer; for the
everyday time verbs like this one, the two are interchangeable.
If each surviving tap then had to trigger real, typed async work,
.pull() would carry the stream into the demand-driven
FxAsync pipeline.
Benchmark
No benchmark for this example. This operator is defined by elapsed time, not by work done: both sides wait out the same windows, so a bar would be measuring Dart's timers rather than either library. Shrinking the windows does not help either — how many values a burst produces would then depend on how fast the machine is, and the two sides could no longer be checked against an identical result. The examples built on timing operators are left unmeasured for that reason; the ones whose delays merely stand in for I/O are benchmarked with those delays set to zero.