Throttle the refresh button

Toss-up async

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.