Arquitecturas Reactivas para Front End
-
Upload
javier-velez-reyes -
Category
Software
-
view
876 -
download
0
description
Transcript of Arquitecturas Reactivas para Front End
JavierVélezReyes@javiervelezreye
ArquitecturasReac-vasdeStreams
ArquitecturasdeFrontend
Octubre2014
@javiervelezreye2
PresentaciónArquitecturasReac:vasdeStreams
Licenciado en informá2ca por la Universidad Politécnica deMadrid (UPM)desdeelaño2001ydoctoren informá2capor laUniversidad Nacional de Educación a Distancia (UNED) desde elaño2009,Javieresinves2gadoryestáespecializadoeneldiseñoy análisis de la colaboración. Esta labor la compagina conac2vidadesdeevangelización,consultoría,mentoringyformaciónespecializadaparaempresasdentrodelsectorIT.Inquieto,ávidolectoryseguidorcercanodelasinnovacionesentecnología.
I.¿QuiénSoy?
II.¿AQuéMeDedico? DesarrolladoFront/Back
EvangelizaciónWebArquitecturaSoVware
Formación&ConsultoríaITE-learning
DiseñodeSistemasdeColaboraciónLearningAnaly2cs
GamificaciónColabora2va
@javiervelezreye
linkedin.com/in/javiervelezreyes
gplus.to/javiervelezreyes
jvelez77
javiervelezreyes
youtube.com/user/javiervelezreyes
JavierVélezReyes@javiervelezreye
1Introducción§ LaWebComoModeloReac2vo§ Arquitecturascentradasenelmodelo§ ArquitecturasdeProgramaciónFuncionalReac2va§ PrincipiosdelasArquitecturasReac2vas
Introd
ucción
Arqu
itecturasRea
c-vasd
eStream
s
@javiervelezreye4
IntroducciónArquitecturasReac:vasdeStreams
A.LaWebComoModeloReac:vo
I.ElCaminoHacialasArquitecturasReac:vas
LaWeb,comoplataformadeinteracción,esunsistemareac2vo.ElárbolDOMquerepresentaenmemoriaeldocumentodelapáginaencursoesunmodelodedatossujetoacambiossobreelquepuedenregistrarsefuncionesescuchadorasparacadaunodeloseventosqueelsistemalanza como señalización de dichos cambios. La programación basada en escuchadores es elmásbásicoynucleardelosmodelosdeconstruccióndeaplica2vosWeb.
index.html
<button id='btn'> <button/>
Click
var btn = document.querySelector('#btn'); var sClicks = document.querySelector('#clicks'); var nClicks = 0; btn.addEventListener('click', function () { clicks.innerHTML = ++nClicks; });
Clicks: <span id="clicks"></span>
@javiervelezreye5
IntroducciónArquitecturasReac:vasdeStreams
B.ArquitecturasCentradasenelModelo
I.ElCaminoHacialasArquitecturasReac:vas
Como evolución del modelo de construcción basado en programación de escuchadores,emergieronunaseriedearquitecturasqueserecogenbajoelacrónicoMV*porsussimilitudesentresí.Todasellascompartenlapremisadequeestáncentradasenunmodelointernocuyoscambios son atendidos por la vista a través de cierta lógica de control. En general esteparaguasrecogediversasvariantesarquitectónicas.
Modelo
Vista Controlador
Usuario
man
ipulaactualiza
MVC
observa usa
Modelo
Adapter
Usuario
man
ipula
actualiza
MVA
observa usa
ModelViewController
El controlador manipula la vista enrespuesta a las interacciones delusuarioyelmodeloactualizalavista
ModelViewAdapter
Elmodelono se comunica con la vista.Es el adaptador el encargado depropagarloscambiosenambaspartes
Vista
@javiervelezreye6
IntroducciónArquitecturasReac:vasdeStreams
B.ArquitecturasCentradasenelModelo
I.ElCaminoHacialasArquitecturasReac:vas
Como evolución del modelo de construcción basado en programación de escuchadores,emergieronunaseriedearquitecturasqueserecogenbajoelacrónicoMV*porsussimilitudesentresí.Todasellascompartenlapremisadequeestáncentradasenunmodelointernocuyoscambios son atendidos por la vista a través de cierta lógica de control. En general esteparaguasrecogediversasvariantesarquitectónicas.
M
V C
HMVC
Modelo
Presenter
Usuario
man
ipula
actualiza
MVP
observa usa
ModelViewControllerJerárquico
LosmodelosMVCsedistribuyenentreelaplicaCvoparacadacomponentequeseorganizanagregaCvamente
ModelViewPresenter
ComoextensióndelMVA,elpatrónMVPhacequeelcontroladorsemantengaalasescuchadeloscambiosenlavistayelmodelo
M
V C
M
V C
Vista
@javiervelezreye7
IntroducciónArquitecturasReac:vasdeStreams
B.ArquitecturasCentradasenelModelo
I.ElCaminoHacialasArquitecturasReac:vas
Como evolución del modelo de construcción basado en programación de escuchadores,emergieronunaseriedearquitecturasqueserecogenbajoelacrónicoMV*porsussimilitudesentresí.Todasellascompartenlapremisadequeestáncentradasenunmodelointernocuyoscambios son atendidos por la vista a través de cierta lógica de control. En general esteparaguasrecogediversasvariantesarquitectónicas.
ModelViewView-Model
La vista y el modelo de vista permanecensincronizadosa travésdeunaarquitecturadeobservadoresymutadores
Vista ModelodeVista
Usuario
MVVM
Observa&interacciona
Databinding
Modeloactualiza
@javiervelezreye8
IntroducciónArquitecturasReac:vasdeStreams
C.ArquitecturasdeProgramaciónFuncionalReac:va
I.ElCaminoHacialasArquitecturasReac:vas
Encontraposicióna laspropuestasanterioresquear2culan su funcionamientoenbaseaunprocesodeescuchay transformacióndeunmodelodedatos internomásomenosexplicitoquerepresentaelestadodelaaplicaciónaparecenlasarquitecturasdeprogramaciónreac2vadondeloseventossonges2onadosporcadenasdetransformaciónfuncionalqueseencargandeprocesarlainteraccióndelusuariodeunamaneradeclara2va,inmutableysinestado.
index.html
<button id='btn'> <button/>
Click
Clicks: <span id="clicks"></span>
CadenadeTransformaciónFuncional
LoseventossonrecogidosdelaplataformaWeby se les hace atravesar una cadena detransformaciones funcionalesparaprocesar losresultados
@javiervelezreye9
IntroducciónArquitecturasReac:vasdeStreams
A.DirigidaporlosDatos
II.PrincipiosdeProgramaciónReac:va
Las arquitecturas de programación funcional reac2va definen cadenas de transformaciónfuncionalquesonatravesadasporflujosdedatosparasuprocesamiento.Sedicequeeste2podesolucionesestádirigidaporlosdatosporqueenellosdescansagranpartedelalógicadelaaplicaciónyelpropiocomportamientoreac2vodelsistema.
Click
click, click, click...
filter
group
take(10)
f
CadenadeTransformación
La cadena de transformación filtra los eventosde usuario, los agrupa por pares si éstos seproducen con cierta frecuencia temporal pararepresentar el doble click yfinalmenteabsorbesólolos10primeros
Comportamientodirigidopordatos
Lanaturalezade losdatosatravesadospor la cadena de transformacióncondicionacuándoseejecutaráf
@javiervelezreye10
IntroducciónArquitecturasReac:vasdeStreams
B.CentradaenlaComposición
II.PrincipiosdeProgramaciónReac:va
Las operacionesque formanpartedel procesamientodedatos enprogramación reac2va seencadenan de forma composi2va demanera que el resultado de cada transformación es laentrada para la siguiente transformación. Para poder ar2cular adecuadamente estacomposicióndebemostenerencuentadosreglasdetransformaciónfuncional.
ElCpodel parámetrodeentradadeuna funcióndebesercompaCbleconelCpodelvalorderetornodevueltopor la funciónanteriorparaque lacomposiciónpuedaarCcularse con éxito. Las arquitecturas reacCvastambién cumplen este requisito puesto que recibeneventoscomoentradaygeneraneventosdesalida
II.Compa:bilidadRango-Dominio
I.DominioSimpleDado que las funciones devuelven un único valor deretorno, el númerodeparámetrosde entradaquepuedeaceptar una función en una composición debe serexactamenteuno.EnelcasodelaprogramaciónreacCva,la información se encapsula en una estructura de datosque representa un evento lo que permite cumplir estacondición
F
GT
U
ElCpodesalidaTdebesercompaCbleconel Cpo de entrada U. En términos OOPdiríamosqueTdebesersubCpodeU
filter
group
f
event
@javiervelezreye11
IntroducciónArquitecturasReac:vasdeStreams
C.TransparenciaReferencial
II.PrincipiosdeProgramaciónReac:va
Elprincipiodetransparenciareferencialpredicaqueentodaespecificaciónfuncionalcorrecta,cualquierfuncióndebepodersubs2tuirseencualquierámbitodeaplicaciónporsuexpresiónfuncionalsinqueelloafectealresultadoobtenido.Equivalentemente,estoimplicaqueelvalorderetornodelasfunciones,comocualquiertransformaciónmatemá2ca,sólopuededependerdesusparámetrosdeentradaynodecondicionesambientales.
f
Estado FuncionesPuras
Se dice que las operaciones de transformaciónsonfuncionespurasentantoquegaranCzanelmantenimiento de la transparencia referencial.Así, su valor de retorno sólo depende de losparámetros de entrada y no del estadoambiental (variables globales, variablesretenidasenámbito léxico,operacionesdeE/S,etc.)
@javiervelezreye12
IntroducciónArquitecturasReac:vasdeStreams
D.ComportamientoIdempotente
II.PrincipiosdeProgramaciónReac:va
Unprincipioenestrecharelaciónconeldetransparenciareferencialesdedecomportamientoidempotente segúnel cual cada funciónde transformacióndebedevolver siempreelmismoresultado para los mismos parámetros de entrada. Esto permite razonar algebraicamentesobrelavalidezdelprocesamientoreac2vo.
La operación filter se encarga de dejarpasar a la cadena composiCva sóloaquellos eventos en los que x Cene unvalor par. Se trata de una operaciónidempotenteporqueparaelmismoeventodeentradasiempreprocedeigual
filter ( x es par )
scan (0)
f
OperaciónIdempotente
La operación scan cuenta el número deeventos que atraviesan la atraviesa ydevuelve un evento con el valor de dichocontador en cada invocación. Se trata deuna operación no idempotente porque elvalor devuelto depende del número deinvocacionesanteriores
OperaciónNoIdempotente
@javiervelezreye13
IntroducciónArquitecturasReac:vasdeStreams
E.InmutabilidaddeDatos
II.PrincipiosdeProgramaciónReac:va
Unúl2moprincipioheredadodelaprogramaciónfuncionalquedebemostenerencuentaenla construcción de arquitecturas reac2vas es el principio de inmutabilidad de datos. Entérminosprác2coslaaplicaciónseesteprincipiosetraduceenquelasfuncionesnuncadebenactualizarlosparámetrosdeentradacomoresultadodesuejecuciónsinosolamentegenerarapar2rdeellosresultadosdesalida.
Los eventos que atraviesan lafunción f son transformadospara generar un resultado desalida
FunciónMutadora
function f(e) { e.value = e.value + 10; return e; }
FunciónNoMutadora
function f(e) { var ne = new Event (e); ne.value = ne.value + 10; return ne; }
Paranomodificareleventoa laentrada, la función f construyeuna nueva copia delmismo y lotransforma para generar elresultadodesalida
JavierVélezReyes@javiervelezreye
2ConceptosEsenciales
§ ArquitecturasWebReac2vas§ VisiónEstá2ca§ VisiónDinámica
Concep
tosE
senciales
Arqu
itecturasRea
c-vasd
eStream
s
@javiervelezreye15
ConceptosEsencialesArquitecturasReac:vasdeStreams
Laprogramaciónfuncionalreac2vaesunmodelodeprogramaciónquepretendedarrespuestaalademandacrecientedenuevossistemasmásflexibles,elás2cosytolerantesafallosapar2rde los principios propios de la programación funcional. Esta aproximación resulta muyventajosa en tanto que produce desarrollos más declara2vos y explícitos centrados en lastransformacionesquedebensufrirlosdatosparasuprocesamiento.
I.ArquitecturasWebReac:vas
Las Arquitectura Web Reac-vas son sistemas soaware queoperanen reaccióna los eventosocurridos sobreelmodelodedatos DOM de laWeb. Cada evento atraviesa una cadena detransformaciónfuncionalparasuprocesamiento.
La lógica de negocio de una arquitecturareacCva queda capturada en la cadena detransformaciones que es atravesada por cadaevento.Estastransformacionessonengeneralinmutables, idempotentes y agnósCcas de lascondicionesambientales
I.ConstrucciónComposi:vaParadójicamente, las operaciones detransformación que arCculan las arquitec-turas reacCvas están en estrecha relacióncon el Cempo ya que éste es un factordeterminantealahoradeconstruirmodelosdecomportamientoreacCvo
II.ModeladoExplicitodelTiempo
@javiervelezreye16
ConceptosEsencialesArquitecturasReac:vasdeStreams
Desde un punto de vista estructural, las arquitecturas de programación funcional reac2vaestán caracterizadas por una colección de abstracciones funcionales. Estas abstracciones seencadenan secuencialmente para que lleven a cabo las tareas de procesamiento ytransformacióndeeventosdesdelafuenteemisoraalossumiderosreceptoresdemaneraquetodalalógicadenegocioseexpresadeformadeclara2vaydistribuidaalolargodelacadena.
II.VisiónEstá:ca
FuenteLafuentees laencargadadeproporcionar loseventosa lacadenadetransformación
CadenadeTransformaciónLas operaciones de transfor-mación funcional se enca-denancomposiCvamente
SumideroAl final de cada cadena se puedencolocar receptores que recogen losdatos procesados e incluso puedenmezclarseconotrascadenas
TransformaciónCadaoperacióndentrodelacadenaes una transformación funcional nomutadora
StreamdeEventosLos eventos provenientes de lafuente de datos fluyen discrecional-mentealolargodelCempo
@javiervelezreye17
ConceptosEsencialesArquitecturasReac:vasdeStreams
A.LíneadeTiempo
III.VisiónDinámica
Elcomportamientodelasarquitecturasreac2vasdeprogramaciónfuncionalseencuentraenestrecharelaciónconelfactor2empo.Enefecto,lalógicadelasoperacionesqueformanpartedelacadenadetransformacióndependecomúnmentedeaspectostalescomoelnúmerodeeventosprocesadoshastaelmomento,sufrecuenciadeapariciónosuperiodo.Estopermitemodelarfácilmentecomportamientossistémicosquedependendel2empo.
Cada evento ocupa unaposiciónsobrelalíneadeCempos
EventoLos streams también pueden generarerrores que se capturan y gesConancomoeventosespeciales
Error
Indica la terminación de lallegada y procesamiento deeventosporpartedelstream
TerminaciónRepresenta el histórico deeventosenunprocesamientode eventos. La punta deflecha indica el momentoactual
Líneade:empo
@javiervelezreye18
ConceptosEsencialesArquitecturasReac:vasdeStreams
B.DiagramasdeReac:vidad
III.VisiónDinámica
La mejor manera de razonar sobre las arquitectura reac2vas es por medio del uso dediagramasdereac2vidad.Undiagramadereac2vidadesunarepresentaciónalternadelíneasde2empoyoperacionesdetransformaciónfuncional.Cadaunadeestasoperacionesrecibecomoentradalalíneade2empoanteriorygeneracomosalidalalíneasubsiguiente.
clicks
groups
size3 2 1
Doubleclick3 2
Cada operación recibeuna línea de Cempocomoentradaygeneraasu salída otra línea deCempo con eventosnuevos
OperacionesCadalíneaesunaproyecciónalo largo del Cempo de lo queocurre en el sistema en unpunto determinado de lacadena
LíneasdeTiempo
buffer(throdle(250ms))
map(getlengthofgroup)
filter(size>1)
@javiervelezreye19
ConceptosEsencialesArquitecturasReac:vasdeStreams
B.DiagramasdeReac:vidad
III.VisiónDinámica
Los diagramas de reac2vidad ofrecen una visión del comportamiento de las arquitecturasreac2vasentornoadosperspec2vasortogonales.Encadaver2calsepuedecomprobarcuálesel proceso de transformación que sufre un evento en un momento del 2empo.Horizontalmente,secontemplaelcomportamientodecadafasealolargodel2empo
clicks
groups
size
Doubleclick
Se razona sobre lo queocurreenuninstantedeCempo con el procesa-miento de un eventoconcretoalo largodelacadena
DimensiónVer:cal
Se razona acerca de cómo secomporta cada fase y elproceso independientementedeladimensiónCempo
DimensiónHorizontal
3 2 1
3 2
buffer(throdle(250ms))
map(getlengthofgroup)
filter(size>1)
@javiervelezreye20
ConceptosEsencialesArquitecturasReac:vasdeStreams
C.OperacionesReac:vas
III.VisiónDinámica
Para completar la descripción del comportamiento dinámico es necesario conocer lasprincipalesoperacionesquepuedenaplicarseparadefinircadenasdetransformación.Elléxicode lasmismas cambia de una librería a otra pero en esencia todas proporcionan elmismojuegodefacilidadesdeclara2vas.
OperacionesdeCreaciónLas operaciones de creación permiten creardisCntas fuentes de eventos en relación adisCntosorígenesasíncronosdedatos
subscribe(f)
OperacionesdeTerminaciónLas operaciones de terminación permitendefinir sumideros al final de una cadenareacCva
stream(css)
values(interval,v)
serie(delay,it)
error(f)
end(f)
@javiervelezreye21
ConceptosEsencialesArquitecturasReac:vasdeStreams
C.OperacionesReac:vas
III.VisiónDinámica
Para completar la descripción del comportamiento dinámico es necesario conocer lasprincipalesoperacionesquepuedenaplicarseparadefinircadenasdetransformación.Elléxicode lasmismas cambia de una librería a otra pero en esencia todas proporcionan elmismojuegodefacilidadesdeclara2vas.
OperacionesdeMezcladeStreamsLasoperacionesdeentrelazadoymezcladestreamsdeeventospermiten fusionarvariosstreamsdeeventosparacrearstreamsdeeventoscompuestos.Estopermitequeunmismostreampuedaserprocesadopormásdeunacadenadecomposicióndeformasimultanea
concat
41
532 76
541 76
merge
41
532
321 54
startWith(v)
v
432
32v 54
5
@javiervelezreye22
ConceptosEsencialesArquitecturasReac:vasdeStreams
C.OperacionesReac:vas
III.VisiónDinámica
Del capítulo anterior ya ha quedado patente que las arquitecturas reac2vas presentan unaclara formulación funcional. Se trata en esencia de definir cadenas de transformación queserán atravesadas por los datos según van generándose. Sin embargo en términos másprác2cosexistenunaseriedecarácterís2casdiferencialesqueresumimosacon2nuación.
OperacionesdeGes:ónTemporalLas operaciones de gesCón del Cempo permiten modelarcomportamientosreacCvosqueCenenencuentacondicionestemporalesen relación a los eventos. Dado que estas funciones dependen de lascondicionesambientalesyfrecuentementenoCenenuncomportamientoidempotente su ajuste al paradigma funcional queda un poco enentredicho.
3 2 7 9
3 2 7 9
hold(<5)
3 2 7 9
7 9
skip(2)
3 2 7 9
3 2
take(2)
3 2 7 9
3 2 7 9
delay(10ms)
throdle(5ms)
@javiervelezreye23
ConceptosEsencialesArquitecturasReac:vasdeStreams
C.OperacionesReac:vas
III.VisiónDinámica
Del capítulo anterior ya ha quedado patente que las arquitecturas reac2vas presentan unaclara formulación funcional. Se trata en esencia de definir cadenas de transformación queserán atravesadas por los datos según van generándose. Sin embargo en términos másprác2cosexistenunaseriedecarácterís2casdiferencialesqueresumimosacon2nuación.
OperacionesdeSecuenciamientoLasoperacionesclásicasdesecuenciamiento(map, reduce, filter) se adaptan al modelounitariodeprocesamientoreacCvo
map(f) filter(f)
3
3
4
7
scan(0,+)
OperacionesdeAsincroníaLas operaciones asíncronas permitengesConar disCntos aspectos relacionadosconelcarácterasíncronodeloseventos
3 4
7
reduce(0,+)
map(p)
p
vp
v
flatMap(p)
JavierVélezReyes@javiervelezreye
3UnFrameworkSencillodeProgramaciónReac-va
§ ModelosdeProgramaciónReac2va§ FrameworkSencillodeProgramaciónReac2va§ Evaluación
UnFram
eworkSencillode
Program
aciónRe
ac-v
a
Arqu
itecturasRea
c-vasd
eStream
s
@javiervelezreye25
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
A.ModelosdeOperaciónPull&Push
I.ModelosdeProgramaciónReac:va
Es posible caracterizar las arquitecturas de programación funcional reac2va en virtud de lanaturalezasíncronaoasíncronadelosdatosqueprocesan.EllodalugarasendosmodelosdeoperaciónconocidosconelnombredePullyPushrespec2vamente.Enelprimercaso,eselsumidero el que pide nuevos datos a la cadenamientas que en el segundo es la fuente laencargadadeempujardichosdatosproac2vamenteencuantoéstossongenerados.
I.ModeloPullEn el modelo pull, el sumidero solicita nuevosdatos y la solicitud recorre ascendentemente lacadenahastallegaralafuente
La fuentees laenCdadpasivaquegeneranuevosdatosbajodemanda
I.ModeloPushEnelmodelopush,amedidaquesedisponendenuevosdatos,lafuentelosempujaporlacadenadetransformaciónhaciaabajo
La fuente es la enCdad acCvaque produce datos y losentregaalacadena
El sumidero es la enCdadacCva que pide a la cadenanuevosdatosprocesadosparaserconsumidos
El sumidero es una enCdadpasiva que se manCene a laescucha para consumir datoscuandollegandesdelacadena
@javiervelezreye26
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
B.ModelosdeComputaciónCon:nua&Discreta
I.ModelosdeProgramaciónReac:va
Ortogonalmente,lasfuentestambiénpuedenclasificarseenvirtuddelanaturalezacon2nuaodiscreta de los datos que procesan. En el primer caso, hablamos demodelos de streamimgdonde losdatossonseñalescon2nuasyperdurablesmientrasqueenel segundocaso,cadadato representaunaocurrenciapuntualenel2empoyelloconformaarquitecturasdirigidasporeventos.
I.ModeloCon:nuoEnelmodelodecomputaciónconCnualosdatossecorrespondenconstreamsllamadosseñalesocomportamientos
Los sistemas reaccionan a loscambiosenelflujodedatos.Aestecambiose lesuele llamarswitching. En este Cpo desistemas la frecuencia demuestreo es uno de losparámetroscaracterísCcos
I.ModeloDiscretoEnelmodelodiscreto losdatos secorrespondencon eventos que se producen en instantespuntualesdelCempo
Los eventos son elementosvehiculares que acarreanvalores de contexto transfor-mados a través de la cadenareacCva
@javiervelezreye27
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
C.Clasificación
I.ModelosdeProgramaciónReac:va
Es posible establecer las dos caracterizaciones anteriores como dos ejes dimensionalesdispuestos ortogonalmente. Ello da lugar a un espacio de clasificación que divide lasarquitecturas reac2vas en cuatro familias. Nosotros centraremos nuestra atención enarquitecturasWebreac2vas.
ModelosCon:nuosBasadosenStreams
ModelosDiscretosBasadosenEventos
Mod
elosSíncron
os
Mod
oPu
llMod
elosAsíncrono
sMod
oPu
sh ProgramaciónWebReac:va
BigDataEventProcessing
ModelodeActores
WebSockets
Iteradores&Generadores
ColeccionesInfinitas
EvaluaciónPerezosa
SignalProcessing
NoiseGenerators
Streammingdedatos
Video&AudioStreams
WebAudioAPI
WebRTC
@javiervelezreye28
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
A.GeneracióndeFuentes
II.FrameworkSencillodeProgramaciónReac:va
Como hemos visto en el capítulo anterior existe una gran variedad de constructores quepermitendefinir fuentes asíncronasque funcionanenmodoPush.Aquínos centraremosenpresentarelcódigointernodelasmáscomúnmenteu2lizadas.
AdaptadordeEventoWebLos adaptadores de eventos son funcionesque recogen eventosWeb y los redirigen auna función manejadora pasada comoargumento en una segunda fase deevaluaciónEn este ejemplo se ve cómo la funciónfromTarget construye una fuente s a parCrdeunselectorcssyunCpodeevento
function fromTarget(css, type) { var target = document.querySelector (css); return function (fn) { target.addEventListener(type, function (e) { fn(e); }); }; } function fromTargetAll(css, type) { var targets = document.querySelectorAll (css); return function (fn) { [].forEach.call(targets, function (target) { target.addEventListener(type, function (e) { fn(e); }); }); }; }
<button id="btn">click</button> ... <script> var s = fromTarget('#btn', 'click'); s(console.log); </script>
@javiervelezreye29
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
A.GeneracióndeFuentes
II.FrameworkSencillodeProgramaciónReac:va
Como hemos visto en el capítulo anterior existe una gran variedad de constructores quepermitendefinir fuentes asíncronasque funcionanenmodoPush.Aquínos centraremosenpresentarelcódigointernodelasmáscomúnmenteu2lizadas.
AdaptadordeColecciónLos adaptadores de colección persiguengenerar fuentes push que iteran circular-mentesobreloselementosdeunacolecciónaintervalosregularesdeCempoLa función fromValues recibe un array devaloresyunintervalodeCempoyconstruyeuna función que emiCrá un evento con elvalorsiguienteen lacoleccióncadavezqueesinvocado
function fromValues (values, ms) { return function (fn) { var idx = 0; var hn = fn || function () {}; setInterval (function () { fn(values[idx]); idx = (idx + 1) % values.length; }, ms || 1000); }; }
var s = fromValues([1,2,3]); s(console.log);
En este sencillo ejemplo, la construcción de lafuenteasíncronadeeventosemitecircularmente,aintervalos regulares de 1 segundo, los elementosdelarraypasadocomoparámetrodeentrada. Loseventos se vinculan al escuchador de salidaestándar
@javiervelezreye30
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
A.GeneracióndeFuentes
II.FrameworkSencillodeProgramaciónReac:va
Como hemos visto en el capítulo anterior existe una gran variedad de constructores quepermitendefinir fuentes asíncronasque funcionanenmodoPush.Aquínos centraremosenpresentarelcódigointernodelasmáscomúnmenteu2lizadas.
AdaptadordeIteraciónLa función serie toma una función genérica fn ydevuelve otra función iteradora que genera valoresconsecuCvosaplicandodichafunciónfromSerie es una fuente push que invoca la seriepasada como parámetro a intervalos regulares deCempo.EstaesunamaneradehacerunadaptadorPushsobreunafuentePullElcódigodeejemplodefinelafunciónincysobreellagenera laseriedenúmerosnaturalesnum.Despuesconstruyeunafuenteylavinculaalasalidaestándar
function serie (fn, base) { var value = base; return function () { value = fn(value); return value; }; } function fromSerie (serie, ms) { return function (fn) { var hn = fn || function () {}; setInterval (function () { var value = serie(); fn(value); }, ms || 1000); }; }
var inc = function (x) { return x + 1; } var num = serie(inc, 0); var s = fromSerie(num, 3000); s(console.log);
@javiervelezreye31
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
B.OperadoresdeTransformación
II.FrameworkSencillodeProgramaciónReac:va
Hastaahoradamossoportealadefinicióndefuentesdediferentes2posqueseconectanenmodoPushasumiderosdirectamente.Definamosacon2nuación,lacoleccióndeoperadoresdetransformaciónquepodránseru2lizadosparadefinircadenasennuestroframework.
OperadormapEl operador map es una función de orden superiorquerecibecomoparámetrounafunciónfngenéricay devuelve otra función como resultado. Elcomportamientodedichafunciónesinvocarafnconlos argumentos pasados como parámetro en estafunciónderetornoEl siguiente código de ejemplo muestra un usoprotoipico de la funciónmapque transforma cadadatodeentradaensucuadrado.Paraelloseaplicamap con una función anónima que define elcuadradoyluegoseaplicalafunciónresultante
function map (fn) { return function () { return fn.apply(this, arguments); }; }
var sqr = map(function (x) { return x * x; }); sqr(3); // 9
0
1
1
1
2
4
3
9
map(x=>x*x)
@javiervelezreye32
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
B.OperadoresdeTransformación
II.FrameworkSencillodeProgramaciónReac:va
Hastaahoradamossoportealadefinicióndefuentesdediferentes2posqueseconectanenmodoPushasumiderosdirectamente.Definamosacon2nuación,lacoleccióndeoperadoresdetransformaciónquepodránseru2lizadosparadefinircadenasennuestroframework.
OperadorfilterEl operador filter recibe un predicado lógico comoparámetroygeneraotrafuncióncomoretornocuyopropósito es filtrar sólo aquellos argumentos quesaCsfagandichopredicado.SielfiltronoespasadoentonceslafuncióndevuelveundefinedEn el ejemplo siguiente se aplica el operador filtersobreunpredicadológicoquedeterminasiunvalores par. El resultado es una función que sólo dejafiltrarloseventosconvalorpar.
function filter (fn) { return function () { var out = fn.apply (this, arguments); if (out) return arguments[0]; }; }
var even = filter(function (x) { return x % 2 === 0; }); even(2); // 2 even(3); // undefined
0
1
1 2
2
3
filter(x=>x%2===0)
@javiervelezreye33
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
B.OperadoresdeTransformación
II.FrameworkSencillodeProgramaciónReac:va
Hastaahoradamossoportealadefinicióndefuentesdediferentes2posqueseconectanenmodoPushasumiderosdirectamente.Definamosacon2nuación,lacoleccióndeoperadoresdetransformaciónquepodránseru2lizadosparadefinircadenasennuestroframework.
OperadorscanEloperadorscanesunoperadorconmemoria.Cadanuevodato locombinaconunacumuladorretenidoen ac a través de una función binaria de reducciónpasada como parámetro. El valor inicial delacumulador sepasacomosegundoparámetrobdelafunciónEn el ejemplo adjunto se aplica el operador scansobrelafunciónreductoradelasumayconbaseen0. Como resultado, cada evento devuelve la sumaacumuladadelosvaloresenloseventosprocesadoshastaelmomento
function scan (fn, b) { var ac = b; return function () { var args = [].slice.call (arguments); ac = fn.apply (this, [ac].concat(args)); return ac; }; }
var add = scan(function (x, y) { return x + y; }, 0); add(2); // 2 = 2 + 0 add(3); // 5 = 3 + 2 add(4); // 9 = 4 + 5
0
0
1
1
2
3
3
6
reduce((x,y)=>x+y,0)
@javiervelezreye34
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
C.EncadenamientodeOperadores
II.FrameworkSencillodeProgramaciónReac:va
Nuestrosoperadoresaplican funcionesde transformaciónydevuelvenel resultadodedichaaplicación. Como tal no pueden encadenarse de acuerdo a una sintaxis de API fluida. Esnecesariodefinirunafunciónqueadaptecadafunciónadecuadamenteenestesen2do.
var numbers = fromValues([2,3,4]) .map(sqr) .filter(even) .scan(add, 0) .end(); numbers(console.log); sqr
even
add
function fluent (hn) { var cb = hn || function () {}; return function (fn) { return function () { cb(fn.apply(this, arguments)); return this; }; }; }
Se pretende transformar de forma transparentelas funcionesmap, filter y scan para que puedanserencadenadasennotacióndepuntoamododeAPIfluida
El ordenenque se incluyen lastransformaciones sqr, even yadd en la expresión de APIfluida corresponde al orden enque éstas son añadidas en lacadenareacCva
Necesitamos transformar los operadores a través de lafunción fluid que genera una función para ejecutar eloperador,entregarelresultadoaunmanejadorydevolverunareferenciaalobjetodecontextosobreelqueseaplicael operador punto para poder seguir encadenandooperadores
@javiervelezreye35
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
D.ComposicióndeTransformaciones
II.FrameworkSencillodeProgramaciónReac:va
Unavezlogradoelobje2vodeencadenaroperadoresyantesdecerrarnuestroframeworkesnecesariodefinirunafuncióndesecuenciamientoqueapliquecomposi2vamentecadafuncióndetransformacióndentrodelacadena.Veamoscomohacerlo.
function sequence (fns) { return function (x) { return fns.reduce (function (ac, fn) { return (ac !== void 0) ? fn(ac) : void 0; }, x); }; }
Lafunciónsequencerecorreelarraydefuncionespasado como parámetro y lo aplica composiCva-mente a parCr del parámetro x. Como se ve laimplementación hace uso de una estrategia dereducción conbase en x y garanCzaque en todomomento cada función aplicada devuelve unresultadononulo
var s = sequence([ map(sqr), filter(even), scan(add, 0) ]); s(3) // undefined (even(9) === false) S(2) // 4
Para entendermejor como opera esta función pensemosenunejemploconelarrayde funciones [sqr,even,add].Pretendemosconstruirunafunciónquecuandoseinvoquesobre x devuelva el resultado composiCvo equivalente aevaluarlaexpresiónadd(even(sqr(x)))
@javiervelezreye36
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
E.ConstructorStream
II.FrameworkSencillodeProgramaciónReac:va
Despuésdetodoestetrabajosólorestadefinirel constructor Stream que proporciona elobjetodecontextodondesedefinirálacadenade composición, incluir las funciones anterio-resyañadiralgunalógicaadicionalparasopor-tarelprocesoderegistrodeescuchadores.
PatrónStreamPush
function Stream (source) { var fns = []; var lns = []; var define = fluent (function (fn) { fns.push (fn); }); return { map : define (map), filter: define (filter), scan : define (scan), end: function () { var seq = sequence(fns); source(function (data) { var result = seq(data); lns.forEach(function (ln) { if (result) ln (result); }); }); return { listen: function (ln) { lns.push(ln); } }; } }; }
La colección lns acumula los escuchadores que seregistran al stream para ser noCficados de cadanuevoresultadoprocesadoLafunciónendaplicasequenceunavezparaobtenerla cadena de composición y después arranca lafuente con un manejador que obCene el siguienteresultado y si es definido lo publica a cadaescuchadorComoretornosedevuelveunobjetoconunmétodolisten que permite registrar nuevos manejadoresasociadosaescuchadoresinteresados
@javiervelezreye37
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
Antesdeterminarrepasaremosunpardeejemplossencillosquepuedenserdesarrolladosconnuestro framework de forma declara2va. Para cada ejemplo incluiremos a efectoscompara2voslaversióntradicionalbasadaeneventosWebparaapreciarsusdiferencias.
III.Evaluación
var data = serie (function (x) { return x + 1; }, 0); var source = fromSerie(data); var stream = Stream (source) .map (function (e) { return e * e; }) .filter (function (e) { return e % 2 === 0}) .scan (function (a, e) { return a + e; }, 0) .end (); stream.listen (console.log);
Laseriededatosgenerauniteradordenaturales que se emplea como fuentepush para una cadena de trasforma-dores [sqr,event,add].Trasfinalizar ladeclaración de la cadena, se invoca elmétodo listen para registrar a laconsolacomoúnicoescuchador
SumadeCuadradosPares
var idx = 0; var sqr = function (n) { var sqrn = n * n; if (sqrn % 2 === 0) console.log (sqrn); idx++; setTimeout(function () { sqr(n+1); }, 1000); }; sqr(0);
La versión imperaCva de este problema esconsiderablemente menos declaraCva que laformareacCva.Ademássetratadeunasoluciónconestadodondeelestadonoestáencapsuladosinomantenidoporunavariableexternaidx.
Reac:vo
Clásico
@javiervelezreye38
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
Antesdeterminarrepasaremosunpardeejemplossencillosquepuedenserdesarrolladosconnuestro framework de forma declara2va. Para cada ejemplo incluiremos a efectoscompara2voslaversióntradicionalbasadaeneventosWebparaapreciarsusdiferencias.
III.Evaluación
En el enfoque clásico se uClizanvariables para referir los elementos(display & btns) y para mantener elestado (count) así comoestructurasdecontroldeflujoparaarCcularelprocesoderegistrodeescuchadores
ContadordeClicks
<button id="up" class="btn">Up</button> <button id="down" class="btn">Down</button> <span id="display"></span> <script> var count = 0; var display = document.querySelector('#display'); var btns = document.querySelectorAll('.btn'); var register = function (idx) { btns[idx].addEventListener ('click', function (e) { if (e.currentTarget.id === 'up') count++; if (e.currentTarget.id === 'down') count--; display.innerHTML = count; }); }; for (var idx=0; idx < btns.length; idx++) register(idx); </script>
Clásico
Up Down 7
@javiervelezreye39
UnFrameworkSencillodeProgramaciónReac2vaArquitecturasReac:vasdeStreams
Antesdeterminarrepasaremosunpardeejemplossencillosquepuedenserdesarrolladosconnuestro framework de forma declara2va. Para cada ejemplo incluiremos a efectoscompara2voslaversióntradicionalbasadaeneventosWebparaapreciarsusdiferencias.
III.Evaluación
LaversiónreacCvaresultamuchomásdeclaraCvaylimpia.Primero se crea una fuente adaptadora de eventos clicksobre el target .btn y después se define una cadenaformadapordosoperaciones, laprimera idenCficaelpasode incrementoquesedebeaplicara lasumay lasegundarealizalasuma.Aquínoexistecontadorexplícito
ContadordeClicks
var source = fromTargetAll('.btn', 'click'); var stream = Stream (source) .map (function (e) { return e.currentTarget.id === 'up' ? 1 : -1 }) .scan (function (a, e) { return a + e; }, 0) .end (); stream.listen (function (n) { document.querySelector('#display').innerHTML = n; });
Reac:vo
Up Down 7
@javiervelezreye40
PreguntasArquitecturasReac:vasdeStreams
Eventos
StreamComposiciónReac:vidad
JavierVélezReyes@javiervelezreye
JavierVélezReyes@javiervelezreye
ArquitecturasReac-vasdeStreams
ArquitecturasdeFrontend
Octubre2014