本页尚未翻译,因此以英文显示。 参与翻译

Debounce the search box

Toss-up async

Requirement

A user types f, fx, fxd in a quick burst, pauses, then types fxdart. Search only when the typing has been quiet for 160 ms — so exactly two searches run (fxd and fxdart) — and print each result. The keystroke schedule is simulated in the code; both versions must print the lines shown under Expected output.

Expected output
3 results for "fxd"
12 results for "fxdart"

Side by side

RxDart

FxDart

Why they differ

They don't. This is a push problem in its purest form — the interesting thing is not the values but when they stop arriving — and both panels say it the same way: debounce the event stream by 160 ms, search each surviving query, collect. RxDart spells it debounceTime; fxdart spells it fxEvents(...).debounce(...). Operator for operator, the two chains are equivalent, down to the trailing value flushed at close.

That is deliberate: fxdart's events layer absorbed the Rx approach for the push side. fxEvents is a thin wrapper chain over plain Dart Streams — never an extension, so it collides with nothing, rxdart included — giving time-based operators a home the pull pipelines rightly refused to be. RxDart's operator catalog remains far larger; fxdart covers the everyday push verbs and stops. And when the debounced queries should feed typed, demand-driven work — ordered concurrent fetches, typed error handling — .pull() is the door back into the 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.