Habilitar el envío cuando el formulario es válido

Empate async

Requisito

Un formulario de registro tiene dos campos. El campo de email emite nam, luego nam@fx.dev; el campo de contraseña emite hunter2, luego box-belt-42 — en desplazamientos fijos intercalados. Tras cada cambio una vez que ambos campos hayan emitido, re-evalúa el par de últimos valores (válido = el email contiene @, la contraseña ≥ 8 caracteres) e imprime el estado combinado — tres líneas de los cuatro eventos de campo, porque el primer cambio aterriza antes de que la contraseña haya hablado; termina con el estado final del botón de envío. Las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
email=nam password=hunter2 -> disabled
email=nam@fx.dev password=hunter2 -> disabled
email=nam@fx.dev password=box-belt-42 -> enabled
submit: enabled

Lado a lado

RxDart

FxDart

Por qué difieren

No difieren. El estado de último-valor-por-fuente es el combinador que define el modelo push, y ambos paneles lo declaran en una línea: retener el valor más nuevo de cada campo, esperar a que ambos hayan hablado, re-emitir el par en cada cambio de cualquiera de los lados. RxDart escribe Rx.combineLatest2(emails(), passwords(), ...); fxdart escribe fxEvents(emails()).combineLatest(passwords(), ...). La misma regla de espera, la misma re-emisión por cualquiera de los lados, el mismo cierre-cuando-ambos-cierran — la fusión etiquetada con pliegue que el panel de fxdart solía fabricar a mano ha desaparecido.

La capa de eventos de fxdart absorbe el enfoque Rx exactamente para esta clase de trabajo: una cadena envoltorio deliberada sobre Streams llanos — no una extensión, así que convive con rxdart o cualquier otra biblioteca de streams sin conflictos — que porta los combinadores de último valor que los pipelines pull no pueden tener. Una salvedad honesta se mantiene: el catálogo de operadores de RxDart sigue siendo mucho más amplio que la capa de eventos de fxdart. Cuando el estado combinado del formulario deba gobernar trabajo tipado y dirigido por demanda — digamos, una llamada de envío validada con errores tipados — .pull() cruza desde los pares en vivo al pipeline FxAsync.

Benchmark

Sin benchmark para este ejemplo. Este operador se define por el tiempo transcurrido, no por el trabajo realizado: ambos lados esperan las mismas ventanas, así que una barra estaría midiendo los temporizadores de Dart y no las librerías. Acortar las ventanas tampoco sirve — cuántos valores produce una ráfaga pasaría a depender de lo rápida que sea la máquina, y ya no se podría comprobar que ambos lados dan un resultado idéntico. Por eso los ejemplos construidos sobre operadores de temporización se dejan sin medir; los que solo usan retardos para simular E/S sí se miden, con esos retardos puestos a cero.