SlideShare une entreprise Scribd logo
1  sur  53
Télécharger pour lire hors ligne
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.velez.reyes@gmail.com	
  
Modelo	
  de	
  Paso	
  de	
  Con,nuaciones,	
  Eventos,	
  
Promesas	
  y	
  Generadores	
  	
  
Programación	
  Asíncrona	
  en	
  
Node	
  JS	
  	
  
Mayo	
  2014	
  
@javiervelezreye	
  1-­‐2	
  	
  
Presentación	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
Licenciado	
   en	
   informá2ca	
   por	
   la	
   Universidad	
   Politécnica	
   de	
  
Madrid	
  (UPM)	
  desde	
  el	
  año	
  2001	
  y	
  doctor	
  en	
  informá2ca	
  por	
  la	
  
Universidad	
   Nacional	
   de	
   Educación	
   a	
   Distancia	
   (UNED)	
   desde	
   el	
  
año	
  2009,	
  Javier	
  es	
  inves2gador	
  y	
  está	
  especializado	
  en	
  el	
  diseño	
  
y	
   análisis	
   de	
   la	
   colaboración.	
   Esta	
   labor	
   la	
   compagina	
   con	
  
ac2vidades	
  de	
  evangelización,	
  consultoría,	
  mentoring	
  y	
  formación	
  
especializada	
  para	
  empresas	
  dentro	
  del	
  sector	
  IT.	
  Inquieto,	
  ávido	
  
lector	
  y	
  seguidor	
  cercano	
  de	
  las	
  innovaciones	
  en	
  tecnología.	
  
I.	
  ¿Quién	
  Soy?	
  
	
  
II.	
  ¿A	
  Qué	
  Me	
  Dedico?	
  
	
  
E-­‐learning	
  
Diseño	
  de	
  Sistemas	
  de	
  Colaboración	
  
Learning	
  Analy2cs	
  
Gamificación	
  Colabora2va	
  
Diseño	
  Instruccional	
  
Desarrollado	
  Front/Back	
  
Evangelización	
  Web	
  
Arquitectura	
  SoZware	
  
Formación	
  &	
  Consultoría	
  IT	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.veler.reyes@gmail.com	
  
1	
  Introducción	
  
§  Programación	
  Secuencial	
  
§  Programación	
  Asíncrona	
  
§  Modelos	
  de	
  Programación	
  Asíncrona	
  
§  Un	
  ejemplo	
  
Introducción	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
@javiervelezreye	
  1-­‐4	
  	
  
Introducción	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Programación	
  Secuencial	
  
	
  
Tradicionalmente,	
   el	
   modelo	
   de	
   ejecución	
   que	
   u2lizan	
   la	
   mayoría	
   de	
   los	
   lenguajes	
   y	
  
paradigmas	
   de	
   programación	
   se	
   corresponde	
   con	
   un	
   tratamiento	
   secuencial	
   del	
   cuerpo	
   del	
  
programa.	
  Un	
  programa	
  es	
  entendido	
  como	
  una	
  secuencia	
  de	
  instrucciones	
  que	
  se	
  ejecutan	
  
ordenadamente	
  y	
  donde	
  la	
  ejecución	
  de	
  cada	
  operación	
  no	
  da	
  comienzo	
  hasta	
  que	
  no	
  termina	
  
la	
  anterior.	
  
Se	
  dice	
  que	
  las	
  operaciones	
  son	
  bloqueantes	
  ya	
  
que	
  bloquean	
  el	
  flujo	
  de	
  ejecución	
  del	
  programa	
  
llamante	
  impidiendo	
  que	
  la	
  siguiente	
  instrucción	
  
comience	
  hasta	
  que	
  la	
  anterior	
  haya	
  terminado	
  
Operaciones	
  bloqueantes	
   S1	
  
S2	
  
S3	
  
S4	
  
El	
   programa	
   se	
   ejecuta	
   de	
   principio	
   a	
   fin	
  
respetando	
   el	
   orden	
   correlaEvo	
   que	
   cada	
  
instrucción	
   guarda	
   con	
   la	
   instrucción	
  
anterior	
  y	
  siguiente	
  
Ejecución	
  secuencial	
  
Con	
   este	
   esquema	
   resulta	
   fácil	
   razonar	
   acerca	
  
del	
   comportamiento	
   del	
   programa	
   si	
   éste	
   se	
  
concibe	
  como	
  un	
  proceso	
  de	
  transformación	
  de	
  
estado	
  reflejado	
  en	
  las	
  variables	
  a	
  lo	
  largo	
  del	
  
Eempo	
  
Razonamiento	
  basado	
  en	
  estado	
  
E	
  1	
  
E	
  2	
  
E	
  3	
  
E	
  0	
  
@javiervelezreye	
  1-­‐5	
  	
  
Introducción	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Programación	
  Asíncrona	
  
	
  
La	
   programación	
   asíncrona	
   establece	
   la	
   posibilidad	
   de	
   hacer	
   que	
   algunas	
   operaciones	
  
devuelvan	
   el	
   control	
   al	
   programa	
   llamante	
   antes	
   de	
   que	
   hayan	
   terminado	
   mientras	
   siguen	
  
operando	
   en	
   segundo	
   plano.	
   Esto	
   agiliza	
   el	
   proceso	
   de	
   ejecución	
   y	
   en	
   general	
   permite	
  
aumentar	
  la	
  escalabilidad	
  pero	
  complica	
  el	
  razonamiento	
  sobre	
  el	
  programa.	
  
S1	
  
S2	
  
S3	
  
S4	
  
E	
  1	
  
E	
  2’	
  
E	
  3’	
  
E	
  0	
  
Ahora	
  algunas	
  operaciones	
  son	
  no	
  bloqueantes	
  
ya	
   que	
   devuelven	
   el	
   control	
   al	
   programa	
  
llamante	
   antes	
   de	
   su	
   terminación	
   mientras	
  
siguen	
  ejecutando	
  en	
  segundo	
  plano	
  
Operaciones	
  no	
  bloqueantes	
  
La	
   falta	
   de	
   secuencialidad	
   estricta	
   en	
   la	
  
ejecución	
   del	
   programa	
   hace	
   diOcil	
   determinar	
  
el	
  estado	
  al	
  comienzo	
  de	
  cada	
  operación	
  
Imposible	
  razonar	
  sobre	
  el	
  estado	
  
Ya	
   no	
   se	
   manEene	
   el	
   orden	
  
secuencial	
   puesto	
   la	
   ejecución	
   de	
   la	
  
instrucción	
  que	
  sigue	
  a	
  un	
  operación	
  
no	
   bloqueante	
   se	
   adelanta	
   antes	
   de	
  
que	
   dicha	
   no	
   bloqueante	
   haya	
  
finalizado	
  
Ejecución	
  no	
  secuencial	
  
La	
   asincronía	
   permite	
   que	
   los	
  
siguientes	
   procesos	
   en	
   espera	
  
adelanten	
  su	
  ejecución	
  
Aumento	
  de	
  la	
  escalabilidad	
  
@javiervelezreye	
  1-­‐6	
  	
  
Introducción	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Programación	
  Asíncrona	
  
	
  
La	
  programación	
  asíncrona	
  	
  resulta	
  ventajosa	
  ya	
  
que	
   aumenta	
   el	
   throughput	
   soportado.	
   Esta	
  
ventaja	
  le	
  está	
  haciendo	
  coger	
  mucha	
  tracción	
  
dada	
   la	
   demanda	
   de	
   sistemas	
   de	
   alta	
  
escalabilidad	
  que	
  se	
  requieren	
  en	
  Internet.	
  
S1	
  
S2	
  S3	
  
S4	
  
El	
   principal	
   problema	
   de	
   la	
   programación	
  
asíncrona	
   se	
   refiere	
   a	
   cómo	
   dar	
   con2nuidad	
   a	
  
las	
   operaciones	
   no	
   bloqueantes	
   del	
   algoritmo	
  
una	
  vez	
  que	
  éstas	
  han	
  terminado	
  su	
  ejecución.	
  
Lo	
  Bueno	
   Lo	
  Malo	
  
Startup	
  
Shutdown	
  
Cola	
  de	
  Procesos	
  
entrantes	
  
¿cómo	
  conEnuamos?	
  ¿cómo	
  
recuperamos	
  el	
  estado	
  en	
  
este	
  punto?	
  ¿cómo	
  obtengo	
  
los	
  resultados?	
  
@javiervelezreye	
  1-­‐7	
  	
  
Introducción	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
III.	
  Modelos	
  de	
  Programación	
  Asíncrona	
  
	
  
Es	
  el	
  modelo	
  de	
  asincronía	
  definido	
  dentro	
  de	
  
Node	
   JS.	
   Cada	
   función	
   recibe	
   información	
  
acerca	
   de	
   cómo	
   debe	
   tratar	
   el	
   resultado	
   –	
   de	
  
éxito	
   o	
   error	
   –	
   de	
   cada	
   operación.	
   Requiere	
  
orden	
  superior	
  	
  
Se	
  u2liza	
  una	
  arquitectura	
  dirigida	
  por	
  eventos	
  
que	
  permite	
  a	
  las	
  operaciones	
  no	
  bloqueantes	
  
informar	
   de	
   su	
   terminación	
   mediantes	
   señales	
  
de	
   éxito	
   o	
   fracaso.	
   Requiere	
   correlación	
   para	
  
sincronizar	
  
I.	
  Modelo	
  de	
  Paso	
  de	
  ConQnuaciones	
   II.	
  Modelo	
  de	
  Eventos	
  	
  	
  
Para	
  dar	
  respuesta	
  al	
  problema	
  anterior	
  –	
  cómo	
  dar	
  tratamiento	
  de	
  con2nuidad	
  al	
  resultado	
  
de	
   las	
   operaciones	
   no	
   bloqueantes	
   una	
   vez	
   que	
   éstas	
   han	
   terminado	
   –	
   se	
   han	
   establecido	
  
diferentes	
  modelos	
  de	
  programación	
  asíncrona.	
  Las	
  bondades	
  de	
  dichos	
  modelos	
  se	
  valoran	
  en	
  
términos	
   de	
   cuánto	
   permiten	
   aproximar	
   la	
   programación	
   asíncrona	
   a	
   un	
   esquema	
   lo	
   más	
  	
  
parecido	
  al	
  secuencial.	
  
Se	
   razona	
   con	
   los	
   valores	
   de	
   retorno	
   de	
   las	
  
operaciones	
   no	
   bloqueantes	
   de	
   manera	
  
independiente	
  del	
  momento	
  del	
  2empo	
  en	
  que	
  
dichos	
  valores	
  –	
  de	
  éxito	
  o	
  fallo	
  –	
  se	
  obtengan	
  
Se	
   u2lizan	
   generadores	
   para	
   devolver	
  
temporalmente	
  el	
  control	
  al	
  programa	
  llamante	
  
y	
  retornar	
  en	
  un	
  momento	
  posterior	
  a	
  la	
  ru2na	
  
restaurando	
   el	
   estado	
   en	
   el	
   punto	
   que	
   se	
  
abandonó	
  su	
  ejecución	
  
III.	
  Modelo	
  de	
  Promesas	
   IV.	
  Modelo	
  de	
  Generadores	
  
@javiervelezreye	
  1-­‐8	
  	
  
Introducción	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
IV.	
  Un	
  ejemplo	
  
	
  
Para	
  entender	
  compara2vamente	
  cada	
  uno	
  de	
  estos	
  cuatro	
  modelos	
  u2lizaremos	
  a	
  lo	
  largo	
  de	
  
esta	
   charla	
   un	
   sencillo	
   ejemplo	
   que	
   expone	
   los	
   3	
   2pos	
   de	
   problemas	
   caracterís2cos	
  
relacionados	
  con	
  el	
  control	
  de	
  flujo	
  dentro	
  de	
  programas	
  asíncronos.	
  
Dada	
   una	
   colección	
   de	
   ficheros,	
   leer	
   su	
  
contenido	
  y	
  contabilizar	
  el	
  número	
  total	
  de	
  
ocurrencias	
   de	
   cada	
   carácter	
   contenido	
  
dentro	
  de	
  los	
  mismos	
  
	
  
1.  Leer	
  cada	
  fichero	
  en	
  paralelo	
  
2.  Contabilizar	
  su	
  número	
  de	
  ocurrencias	
  
3.  Sumar	
  los	
  resultados	
  
init	
  
read	
  
count	
  
add	
  
¿Cómo	
  paralelizar?	
  
¿Cómo	
  secuenciar?	
  
¿Cómo	
  sincronizar?	
  
Sequen,al.js	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.veler.reyes@gmail.com	
  
2	
  Node	
  JS	
  como	
  
Lenguaje	
  Asíncrono	
  
§  La	
  Asincronía	
  de	
  Node	
  JS	
  
§  Principios	
  Arquitectónicos	
  de	
  Node	
  JS	
  
§  Arquitectura	
  de	
  Node	
  JS	
  
Node	
  JS	
  como	
  Lenguaje	
  Asíncrono	
  	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
@javiervelezreye	
  1-­‐10	
  	
  
Node	
  JS	
  como	
  Lenguaje	
  Asíncrono	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  La	
  Asincronía	
  de	
  Node	
  JS	
  
	
  
Parece	
  natural	
  pensar	
  que	
  la	
  programación	
  asíncrona	
  exige	
  de	
  un	
  contexto	
  mul2-­‐hilo	
  ya	
  que	
  el	
  
carácter	
   no	
   bloqueante	
   se	
   consigue	
   por	
   medio	
   de	
   una	
   suerte	
   de	
   ejecución	
   simultanea	
   que	
  
transcurre	
  en	
  un	
  segundo	
  plano	
  del	
  flujo	
  principal	
  del	
  programa.	
  Sin	
  embargo,	
  esto	
  no	
  implica	
  
necesariamente	
  un	
  contexto	
  de	
  ejecución	
  concurrente	
  ya	
  que	
  las	
  operaciones	
  no	
  bloqueantes	
  
pueden	
  ejecutarse	
  de	
  forma	
  aislada.	
  
Node	
   JS	
   is	
   a	
   pladorm	
   built	
   on	
   Chrome's	
   JavaScript	
  
run2me	
   for	
   easily	
   building	
   fast,	
   scalable	
   network	
  
applica2ons.	
   Node	
   JS	
   uses	
   an	
   event-­‐driven,	
   non-­‐
blocking	
   I/O	
   model	
   that	
   makes	
   it	
   lightweight	
   and	
  
efficient,	
   perfect	
   for	
   data-­‐intensive	
   real-­‐2me	
  
applica2ons	
  that	
  run	
  across	
  distributed	
  devices.	
  
Node	
  JS	
  es	
  un	
  lenguaje	
  single-­‐thread	
  pero	
  que	
  
aplica	
   mul2-­‐threading	
   en	
   los	
   procesos	
   de	
  
entrada	
   salida	
   y	
   es	
   ahí	
   donde	
   se	
   aplica	
   el	
  
carácter	
  no	
  bloqueante	
  
Modelo	
  no	
  bloqueante	
  de	
  E/S	
  
Node	
   JS	
   u2liza	
   alterna2vamente,	
   como	
  
veremos,	
  el	
  modelo	
  de	
  paso	
  de	
  con2nuaciones	
  
y	
  el	
  de	
  eventos	
  si	
  bien	
  su	
  arquitectura	
  general	
  
está	
  dirigida	
  por	
  un	
  loop	
  general	
  de	
  eventos	
  
Arquitectura	
  dirigida	
  por	
  eventos	
  
@javiervelezreye	
  1-­‐11	
  	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
Node	
  JS	
  como	
  Lenguaje	
  Asíncrono	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Principios	
  Arquitectónicos	
  de	
  Node	
  JS	
  
	
  
A	
   pesar	
   de	
   que	
   recientemente	
   Node	
   JS	
   está	
   recibiendo,	
   especialmente	
   desde	
   ciertas	
  
comunidades	
  compe2doras,	
   	
  fuertes	
  crí2cas	
  rela2vas	
  a	
  su	
  aprovechamiento	
  de	
  los	
  ciclos	
  de	
  
cómputo	
   por	
   tratarse	
   de	
   un	
   entorno	
   single-­‐thread,	
   su	
   filosoga	
   se	
   basa	
   en	
   tres	
   fuertes	
  
principios	
  arquitectónicos.	
  	
  
Esta	
   experimentalmente	
   comprobado	
   que	
  
procesamiento	
  de	
  las	
  operaciones	
  de	
  E/S	
  es	
  el	
  
que	
   mayor	
   coste	
   implica	
   dentro	
   de	
   las	
  
arquitecturas	
  Hw.	
  
1.	
  La	
  E/S	
  es	
  lo	
  que	
  más	
  coste	
  implica	
  
Como	
   consecuencia	
   el	
   esquema	
   de	
  
comportamiento	
  de	
  Node	
  JS	
  se	
  puede	
  resumir	
  
en	
   aquellas	
   partes	
   del	
   proceso	
   de	
   la	
   pe2ción	
  
que	
   merezca	
   la	
   pena	
   paralelizar	
   (E/S)	
   se	
  
ejecutarán	
   de	
   forma	
   no	
   bloqueante	
   mientras	
  
que	
   el	
   resto	
   ejecuta	
   en	
   un	
   esquema	
   single-­‐
thread	
  
3.	
  Todo	
  en	
  paralelo	
  menos	
  tu	
  código	
  
Dedicar	
  un	
  hilo	
  para	
  enhebrar	
  el	
  procesamiento	
  
de	
   cada	
   solicitud	
   entrante,	
   como	
   hacen	
   otras	
  
arquitecturas	
   servidoras	
   (Apache)	
   resulta	
  
demasiado	
  caro	
  en	
  memoria	
  
2.	
  Dedicar	
  un	
  hilo	
  por	
  solicitud	
  es	
  caso	
  
@javiervelezreye	
  1-­‐12	
  	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
  
Node	
  JS	
  como	
  Lenguaje	
  Asíncrono	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
III.	
  Arquitectura	
  de	
  Node	
  JS	
  
	
  
Node	
   JS	
   is	
   a	
   pladorm	
   built	
   on	
   Chrome's	
   JavaScript	
  
run2me	
   for	
   easily	
   building	
   fast,	
   scalable	
   network	
  
applica2ons.	
  Node	
  JS	
  uses	
  an	
  event-­‐driven,	
  non-­‐blocking	
  
I/O	
  model	
  that	
  makes	
  it	
  lightweight	
  and	
  efficient,	
  perfect	
  
for	
  data-­‐intensive	
  real-­‐2me	
  applica2ons	
  that	
  run	
  across	
  
distributed	
  devices.	
  
Llegan	
   las	
   solicitudes	
   a	
  
Node	
  JS	
  desde	
  el	
  exterior	
  
1.	
  Nueva	
  Solicitud	
  
Un	
  único	
  hilo	
  se	
  encarga	
  de	
  
gesEonar	
   las	
   solicitudes	
  
entrantes	
  
2.	
  GesQón	
  
Las	
   operaciones	
   de	
   E/S	
   se	
  
procesan	
   en	
   paralelo	
   en	
  
modo	
  no	
  bloqueante	
  
3.	
  Ejecución	
  no	
  bloquante	
  
Todo	
  Se	
  Ejecuta	
  en	
  Paralelo	
  
menos	
  tu	
  Código	
  
	
   Cuando	
   la	
   operación	
  
termina	
  vuelve	
  al	
  loop	
  
4.	
  Finaliza	
  la	
  operación	
  
Se	
   ejecuta	
   la	
   lógica	
   de	
  
conEnuidad	
   que	
   procesa	
  
los	
  resultados	
  
5.	
  Procesar	
  resultados	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.veler.reyes@gmail.com	
  
3	
  Modelo	
  de	
  Paso	
  de	
  
Con,nuidades	
  
§  Qué	
  es	
  una	
  Con2nuación	
  
§  Control	
  de	
  Flujo	
  Mediante	
  Con2nuaciones	
  
§  Ejemplo	
  
§  Librerías	
  
§  Conclusiones	
  
Modelo	
  de	
  Paso	
  de	
  Con,nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
@javiervelezreye	
  1-­‐14	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  ConQnuación	
  
	
  
El	
  modelo	
  na2vo	
  que	
  u2liza	
  Node	
  JS	
  en	
  sus	
  APIs	
  para	
  dar	
  soporte	
  a	
  la	
  programación	
  asíncrona	
  
es	
   el	
   de	
   paso	
   de	
   con2nuaciones.	
   Cada	
   operación	
   no	
   bloqueante	
   recibe	
   una	
   función	
   como	
  
úl2mo	
   parámetro	
   que	
   incluye	
   la	
   lógica	
   de	
   con2nuación	
   que	
   debe	
   ser	
   invocada	
   tras	
   la	
  
finalización	
  de	
  la	
  misma	
  tanto	
  para	
  procesar	
  los	
  resultados	
  en	
  caso	
  de	
  éxito	
  como	
  para	
  tratar	
  
los	
  fallos	
  en	
  caso	
  de	
  error.	
  
function div(a, b, callback) {
if (b === 0) callback (Error (...))
else {
var result = a / b;
callback (null, result);
}
}
Proveedor	
  
div (8, 2, function (error, data) {
if (error) console.error (error);
else console.log (data);
});
Cliente	
  
La	
  función	
  de	
  conEnuación	
  permite	
  indicar	
  
a	
   la	
   operación	
   bloqueante	
   como	
   debe	
  
proceder	
   después	
   de	
   finalizada	
   la	
  
operación	
  
Paso	
  de	
  ConQnuación	
  
@javiervelezreye	
  1-­‐15	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  ConQnuaciones	
  
	
  
La	
  manera	
  de	
  proceder	
  dentro	
  de	
  este	
  modelo	
  para	
  establecer	
  flujos	
  de	
  ejecución	
  secuenciales	
  
exige	
  ir	
  encadenando	
  cada	
  función	
  subsiguiente	
  como	
  con2nuación	
  de	
  la	
  anterior	
  donde	
  se	
  
procesarán	
   los	
   resultados	
   tanto	
   en	
   caso	
   de	
   éxito	
   como	
   de	
   fracaso.	
   Esto	
   conduce	
   a	
   una	
  
diagonalización	
  del	
  código	
  que	
  se	
  ha	
  dado	
  en	
  llamar	
  pirámide	
  del	
  infierno	
  (callback	
  hell),	
  por	
  su	
  
falta	
  de	
  manejabilidad	
  prác2ca	
  en	
  cuanto	
  crece	
  mínimamente	
  el	
  número	
  de	
  encadenamientos	
  
secuenciales.	
  
A.	
  Secuenciamiento	
  
mul(2, 3, function (error, data) {
if (error) console.error (error);
else div(data, 4, function (error, data) {
if (error) console.error (error);
else add(data, 5, function (error, data) {
...
});
});
});
mul	
  (2,	
  3)	
  
div	
  (3,	
  4)	
  
add	
  (4,	
  5)	
  
2	
  *	
  3	
  /	
  4	
  +	
  5	
  	
  	
  
@javiervelezreye	
  1-­‐16	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  ConQnuaciones	
  
	
  
La	
  paralelización	
  –	
  ejecución	
  asíncrona	
  –	
  de	
  las	
  operaciones	
  no	
  bloqueantes	
  es	
  inmediata	
  ya	
  
que	
   su	
   mera	
   invocación	
   ejecuta	
   en	
   segundo	
   plano	
   por	
   definición.	
   Para	
   conver2r	
   en	
   no	
  
bloqueantes	
  las	
  operaciones	
  bloqueantes,	
  se	
  requiere	
  un	
  pequeño	
  proceso	
  de	
  encapsulación	
  
funcional	
  que	
  lance	
  la	
  operación	
  en	
  segundo	
  plano.	
  
B.	
  Paralelización	
  
add(2, 3, function (error, data) {...});
sub(3, 4, function (error, data) {...});
add	
  (2,	
  3)	
   sub(3,	
  4)	
  
function doAsync (fn, callback, self) {
return function () {
var allParams = [].slice.call(arguments);
var params = allParams.slice (0, allParams.length - 1);
var callback = allParams[allParams.length - 1];
setTimeout (function () {
var results = fn.apply (self, params)
callback (null, results);
}, 0);
};
}
@javiervelezreye	
  1-­‐17	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  ConQnuaciones	
  
	
  
La	
  sincronización	
  de	
  funciones	
  de	
  con2nuación	
  requiere	
  encadenar	
  al	
  final	
  de	
  cada	
  secuencia	
  
paralela	
  una	
  función	
  de	
  terminación	
  que	
  aplique	
  cierta	
  lógica	
  sólo	
  una	
  vez	
  que	
  se	
  compruebe	
  
que	
  todas	
  los	
  ramas	
  paralelas	
  han	
  terminado.	
  Para	
  implementar	
  esta	
  comprobación	
  se	
  u2lizan	
  
esquemas	
  basados	
  en	
  contadores.	
  
C.	
  Sincronización	
  
function doParallel(fns, endCallback, params) {
var pending = fns.length;
var callback = function (error, data) {
<<processing data && error>>
pending --;
if (pending === 0) {
endCallback();
}
}
for (var index = 0; index <fns.length; index ++) {
fns[index].apply (this, params[index], callback);
}
}
doParallel ([add, sub], function (error, data) {
console.log (data)
}, [[2,3],[4,5]]);
add	
  (2,	
  3)	
   sub	
  (4,	
  5)	
  
console	
  
@javiervelezreye	
  1-­‐18	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
III.	
  Ejemplo	
  
	
  
Dada	
   una	
   colección	
   de	
   ficheros,	
   leer	
   su	
  
contenido	
  y	
  contabilizar	
  el	
  número	
  total	
  de	
  
ocurrencias	
   de	
   cada	
   carácter	
   contenido	
  
dentro	
  de	
  los	
  mismos	
  
	
  
1.  Leer	
  cada	
  fichero	
  en	
  paralelo	
  
2.  Contabilizar	
  su	
  número	
  de	
  ocurrencias	
  
3.  Sumar	
  los	
  resultados	
  
init	
  
read	
  
count	
  
add	
  
Paralelización	
  
Secuenciamiento	
  
Sincronización	
  
Un	
   bucle	
   permite	
   lanzar	
   en	
  
ejecución	
   todos	
   los	
   pares	
   no	
  
bloqueantes	
   de	
   leer-­‐contar	
   de	
  
forma	
  no	
  bloqueante	
  
Cada	
  par	
  leer-­‐contar	
  se	
  encadena	
  
a	
  través	
  del	
  paso	
  de	
  funciones	
  de	
  
conEnuación	
  
Para	
   sincronizar	
   cada	
   rama	
   paralela	
   recibe	
   una	
  
úlEma	
   conEnuación	
   que	
   ejecuta	
   lógica	
   de	
  
terminación	
  una	
  vez	
  que	
  se	
  ha	
  asegurado	
  que	
  todas	
  
las	
  ramas	
  han	
  terminado	
  	
  
Con,nua,ons.js	
  
@javiervelezreye	
  1-­‐19	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
IV.	
  Librerías	
  
	
  
Existen	
  numerosas	
  librerías	
  que	
  pueden	
  ayudarnos	
  a	
  hacer	
  la	
  vida	
  más	
  fácil	
  cuando	
  trabajamos	
  
con	
   un	
   modelo	
   de	
   programación	
   asíncrona	
   basado	
   en	
   con2nuaciones.	
   Algunas	
   de	
   ellas	
   no	
  
están	
   estrictamente	
   relacionadas	
   con	
   la	
   programación	
   asíncrona	
   sino	
   con	
   el	
   paradigma	
  
funcional	
  lo	
  cual	
  se	
  debe	
  a	
  que	
  los	
  mecanismos	
  de	
  inyección	
  de	
  con2nuaciones	
  son	
  en	
  esencia	
  
ar2ficios	
  funcionales.	
  	
  
Async	
  
Fn.js	
  
Join	
  
Async	
   es	
   tal	
   vez	
   la	
   librería	
   más	
   conocida	
   y	
  
ampliamente	
   uElizada	
   para	
   la	
   programación	
  
asíncrona	
   basada	
   en	
   conEnuaciones.	
   Ofrece	
  
métodos	
   de	
   control	
   de	
   flujo	
   variados	
   para	
  
funciones	
  no	
  bloqueantes	
  
Fn.js	
  es	
  una	
  excelente	
  librería	
  que	
  implementa	
  
disEntos	
   métodos	
   de	
   gesEón	
   funcional.	
   Su	
  
aplicabilidad	
   prácEca	
   en	
   este	
   contexto	
   está	
  
relacionada	
   con	
   las	
   capacidades	
   que	
   expone	
  
para	
   generar	
   funciones	
   no	
   bloqueantes	
   y	
  
aplicar	
  currificación	
  
Join	
   es	
   una	
   implementación	
   del	
   método	
   de	
  
sincronización	
   que	
   hemos	
   comentado	
  
anteriormente	
   y	
   resulta	
   similar	
   al	
   que	
   puede	
  
encontrarse	
   en	
   otros	
   lenguajes	
   como	
   C	
   que	
  
opera	
   con	
   threads.	
   También	
   puede	
   usarse	
   en	
  
promesas	
   aunque	
   su	
   uso	
   resulta	
   menos	
  
relevante	
  
@javiervelezreye	
  1-­‐20	
  	
  
Modelo	
  de	
  Paso	
  de	
  Con2nuidades	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
V.	
  Conclusiones	
  
	
  
La	
   programación	
   asíncrona	
   basada	
   en	
  
con2nuidades	
  puede	
  ser	
  una	
  buena	
  opción	
  para	
  
situaciones	
  en	
  que	
  la	
  lógica	
  de	
  control	
  de	
  flujo	
  
es	
   muy	
   sencilla.	
   Tal	
   suele	
   ser	
   el	
   caso	
   de	
  
programas	
  en	
  Node	
  JS	
  que	
  permiten	
  definir	
  una	
  
respuesta	
  no	
  bloqueante	
  a	
  pe2ciones	
  entrantes	
  	
  
No	
  obstante,	
  cuando	
  la	
  lógica	
  de	
  control	
  resulta	
  
mínimamente	
   elaborada	
   el	
   proceso	
   de	
  
razonamiento	
  sobre	
  el	
  programa	
  se	
  complica	
  lo	
  
cual	
  redunda	
  en	
  un	
  código	
  con	
  lógica	
  funcional	
  
distribuida	
   y	
   digcil	
   de	
   leer,	
   entender	
   y	
  
mantener.	
  
Lo	
  Bueno	
   Lo	
  Malo	
  
Sencillo	
  para	
  esquemas	
  
solicitud	
  /	
  respuesta	
  
Alineado	
  con	
  los	
  
esquemas	
  de	
  
programación	
  funcional	
  
Fácil	
  de	
  entender	
  como	
  
mecanismo	
  conceptual	
  	
  
Complejidad	
  en	
  la	
  definición	
  de	
  
una	
  lógica	
  de	
  control	
  de	
  flujo	
  
elaborada	
  
Di`cil	
  establecer	
  
mecanismos	
  de	
  
sincronización	
  	
  	
  
La	
  lógica	
  de	
  control	
  
queda	
  distribuida	
  entre	
  
cada	
  rama	
  no	
  
bloqueante	
  
Di`cil	
  de	
  seguir,	
  leer	
  y	
  
mantener	
  a	
  medida	
  que	
  
crece	
  el	
  código	
  	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.veler.reyes@gmail.com	
  
4	
  Modelo	
  de	
  
Eventos	
  
§  Qué	
  es	
  una	
  Arquitectura	
  Dirigida	
  por	
  Eventos	
  
§  Control	
  de	
  Flujo	
  Mediante	
  Eventos	
  
§  Ejemplo	
  
§  Librerías	
  
§  Conclusiones	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
@javiervelezreye	
  1-­‐22	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  Arquitectura	
  dirigida	
  por	
  Eventos	
  
	
  
Un	
   evento	
   es	
   la	
   señalización	
   de	
   un	
   acontecimiento	
   relevante	
   dentro	
   del	
   ecosistema	
   de	
  
negocio.	
  Anatómicamente	
  están	
  formados,	
  kpicamente,	
  por	
  un	
  2po,	
  una	
  marca	
  de	
  2empo	
  y	
  
un	
   conjunto	
   de	
   datos	
   que	
   caracteriza	
   el	
   contexto	
   en	
   el	
   que	
   se	
   produjo	
   el	
   evento.	
   Las	
  
arquitecturas	
  de	
  eventos	
  (EDA)	
  proporcionan	
  un	
  mecanismo	
  de	
  comunicación	
  entre	
  clientes	
  y	
  
proveedores	
  en	
  relación	
  1:N	
  y	
  con	
  desacoplamiento	
  nominal.	
  Una	
  de	
  sus	
  muchas	
  aplicaciones	
  
es	
  en	
  los	
  problemas	
  de	
  procesamiento	
  asíncrono	
  de	
  datos.	
  
Proveedor	
   Cliente	
  
registro	
  
noEficación	
  
reacción	
  
evento	
  
Arquitectura	
  de	
  Eventos	
  
Se	
   produce	
   una	
   comunicación	
   desacoplada	
  
entre	
   proveedores	
   y	
   clientes	
   a	
   través	
   de	
   un	
  
mecanismo	
   de	
   registro/noEficaciones.	
   Nótese	
  
que	
   en	
   este	
   esquema	
   las	
   flechas	
   no	
   indican	
  
invocaciones	
  sino	
  comunicación	
  indirecta	
  
@javiervelezreye	
  1-­‐23	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  Arquitectura	
  dirigida	
  por	
  Eventos	
  
	
  
En	
  las	
  arquitecturas	
  centralizadas	
  dirigidas	
  por	
  eventos	
  existe	
  un	
  mediador	
  central	
  –	
  bus	
  de	
  
comunicaciones	
   –	
   que	
   se	
   encarga	
   de	
   hacer	
   efec2vo	
   el	
   proceso	
   de	
   registro	
   de	
   los	
   clientes	
  
escuchadores	
  y	
  de	
  lanzar	
  las	
  no2ficaciones	
  bajo	
  demanda	
  de	
  los	
  proveedores	
  a	
  los	
  mismos.	
  
Este	
  mecanismo	
  permite	
  una	
  cardinalidad	
  N:N.	
  Este	
  esquema	
  se	
  conoce	
  bajo	
  el	
  nombre	
  de	
  
patrón	
  PUB/SUB.	
  
Arquitectura	
  Centralizada	
  
Proveedor	
   Cliente	
  
evento	
  
manejador	
  noEficación	
  
Bus	
  
var bus = Bus.create ();
bus.send(‘app.module.event’, data);
var bus = Bus.create ();
bus.receive(‘app.module.event’,
function (data) {
...
});
bus.refuse(‘app.module.event’);
bus.refuseAll();
@javiervelezreye	
  1-­‐24	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  Arquitectura	
  dirigida	
  por	
  Eventos	
  
	
  
En	
   las	
   arquitecturas	
   distribuidas	
   dirigidas	
   por	
   eventos	
   cada	
   proveedores	
   es	
   responsable	
   de	
  
ges2onar	
  la	
  suscripción	
  de	
  sus	
  clientes	
  y	
  de	
  enviar	
  las	
  no2ficaciones	
  cuando	
  se	
  produce	
  un	
  
evento.	
   El	
   mecanismo	
   de	
   comunicación	
   también	
   es	
   desacoplado	
   nominalmente	
   pero	
   la	
  
cardinalidad	
   kpicamente	
   es	
   de	
   1:N	
   entre	
   el	
   proveedor	
   y	
   los	
   clientes.	
   Este	
   esquema	
   se	
  
corresponde	
  con	
  el	
  patrón	
  observador-­‐observable	
  o	
  event	
  emibers	
  en	
  jerga	
  Node	
  JS.	
  
Arquitectura	
  Distribuida	
  
var events = require(‘events’);
var emitter = new events.EventEmitter();
emitter.emit(‘app.module.event’, data);
emmiter.on(‘app.module.event’,
function h(data) {
...
});
bus.removeListener(‘app.module.event’, h);
bus.removeAllListeners(‘app.module.event’);
Proveedor	
   Cliente	
  
registro	
  
noEficación	
  
Manejadores	
  
registrados	
  
@javiervelezreye	
  1-­‐25	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Eventos	
  
	
  
El	
   secuenciamiento	
   dentro	
   de	
   este	
   modelo	
   se	
   consigue	
   a	
   través	
   del	
   encadenamiento	
   de	
  
escuchadores.	
   Los	
   resultados	
   de	
   las	
   operaciones	
   van	
   cayendo	
   en	
   cascada	
   desde	
   la	
   primera	
  
hasta	
  la	
  úl2ma	
  acumulándose	
  parcialmente	
  hasta	
  llegar	
  a	
  un	
  resultado	
  final	
  que	
  es	
  recogido	
  y	
  
procesado	
  por	
  el	
  cliente.	
  
A.	
  Secuenciamiento	
  
var addEmitter = new events.EventEmitter();
var mulEmitter = new events.EventEmitter();
function add(x, y) {
addEmitter.emit(‘result’, x+y);
}
function mul(z) {
addEmitter.on(‘result’, function (data){
mulEmitter.emit(‘result’, data * z);
});
}
mul(5);
mulEmitter.on(‘result’, function (data){
console.log(data);
});
add (2,3);
r	
  =	
  add	
  (x,	
  y)	
  
mul	
  (r,	
  z)	
  
(2	
  +	
  3)	
  *	
  5	
  
@javiervelezreye	
  1-­‐26	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Eventos	
  
	
  
En	
  tanto	
  que	
  las	
  arquitecturas	
  dirigidas	
  por	
  eventos	
  establecen	
  un	
  marcado	
  desacoplamiento	
  
entre	
   los	
   agentes	
   par2cipantes,	
   lo	
   único	
   que	
   es	
   necesario	
   hacer	
   para	
   paralelizar	
   varias	
  
operaciones	
  es	
  hacer	
  que	
  cada	
  una	
  opere	
  de	
  manera	
  independiente	
  y	
  lance	
  eventos	
  cuando	
  
genere	
  resultados.	
  
B.	
  Paralelización	
  
add	
  (2,	
  3)	
   sub(3,	
  4)	
  
var addEmitter = new events.EventEmitter();
var subEmitter = new events.EventEmitter();
function add(data) {
addEmitter.emit(‘result’, x+y);
}
function sub(x, y) {
subEmitter.emit(‘result’, x-y);
}
var emitter = new events.EventEmitter();
function add(x, y) {
emitter.emit(‘add’, x+y);
}
function sub(x, y) {
emitter.emit(‘sub’, x-y);
}
@javiervelezreye	
  1-­‐27	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Eventos	
  
	
  
Finalmente,	
  la	
  sincronización	
  requiere	
  un	
  proceso	
  de	
  escucha	
  de	
  todas	
  las	
  fuentes	
  emisoras	
  de	
  
eventos	
   que	
   operan	
   sobre	
   el	
   final	
   de	
   cada	
   rama	
   paralela.	
   Debe	
   incluirse	
   en	
   las	
   funciones	
  
manejadoras	
   lógica	
   de	
   tratamiento	
   que	
   emita	
   nuevos	
   eventos	
   más	
   generales	
   con	
   datos	
  
resultantes	
  el	
  proceso	
  de	
  sincronización.	
  A	
  esto	
  se	
  le	
  llama	
  correlación	
  de	
  eventos.	
  	
  
C.	
  Sincronización	
  
r1=add	
  (2,	
  3)	
   r2=sub	
  (4,	
  5)	
  
mul	
  (r1,r2)	
  
var addEmitter = new events.EventEmitter();
var subEmitter = new events.EventEmitter();
...
function mul() {
var r;
function h(data) {
if (r) {console.log (r * data)}
else r = data;
};
addEmitter.on (‘result’, h);
subEmitter.on (‘result’, h);
}
mul (); Correlación	
  de	
  Eventos	
  
Existe	
   una	
   gran	
   colección	
   de	
   patrones	
   de	
  
diseño	
   propios	
   de	
   las	
   arquitecturas	
   de	
  
correlación	
   entre	
   los	
   que	
   se	
   cuentan,	
  
transformaciones,	
   agregados,	
   filtros	
   o	
  
abstracciones	
  temporales	
  
@javiervelezreye	
  1-­‐28	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
III.	
  Ejemplo	
  
	
  
Dada	
   una	
   colección	
   de	
   ficheros,	
   leer	
   su	
  
contenido	
  y	
  contabilizar	
  el	
  número	
  total	
  de	
  
ocurrencias	
   de	
   cada	
   carácter	
   contenido	
  
dentro	
  de	
  los	
  mismos	
  
	
  
1.  Leer	
  cada	
  fichero	
  en	
  paralelo	
  
2.  Contabilizar	
  su	
  número	
  de	
  ocurrencias	
  
3.  Sumar	
  los	
  resultados	
  
init	
  
read	
  
count	
  
add	
  
Paralelización	
  
Secuenciamiento	
  
Sincronización	
  
Se	
  lanzan	
  a	
  ejecución	
  de	
  forma	
  iteraEva	
  
todas	
   las	
   ramas	
   secuenciales	
   para	
   que	
  
operen	
  en	
  paralelo	
  emiEendo	
  eventos	
  
La	
  operación	
  read	
  emite	
  eventos	
  de	
  datos	
  leídos	
  del	
  
fichero	
  en	
  bloques	
  de	
  1024	
  bytes.	
  La	
  operación	
  count	
  
escucha	
   esos	
   eventos	
   y	
   genera	
   resultados	
  
acumulaEvamente	
   que	
   emite	
   como	
   evento	
   sólo	
  
cuando	
  read	
  envía	
  la	
  señal	
  de	
  fin	
  de	
  fichero	
  
La	
   operación	
   add	
   sincroniza	
   todas	
   las	
   operaciones	
  
count.	
  Va	
  calculando	
  los	
  totales	
  acumulaEvamente	
  y	
  
sólo	
  emite	
  un	
  evento	
  cuando	
  determina	
  que	
  se	
  han	
  
leído	
  todos	
  los	
  resultados	
  
Events.js	
  
@javiervelezreye	
  1-­‐29	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
IV.	
  Librerías	
  
	
  
Dado	
   que	
   existen	
   dos	
   es2los	
   arquitectónicos	
   que	
   operan	
   dentro	
   del	
   modelo	
   de	
   las	
  
arquitecturas	
  dirigidas	
  por	
  eventos	
  –	
  el	
  centralizado	
  y	
  el	
  distribuido	
  –	
  	
  parece	
  razonable	
  dividir	
  
las	
  contribuciones	
  de	
  librerías	
  que	
  existen	
  entre	
  esas	
  dos	
  categorías.	
  
Events	
  
Events	
   es	
   un	
   módulo	
   estándar	
   de	
   Node	
   JS	
  
uElizado	
   para	
   trabajar	
   con	
   eventos.	
   Dispone	
   de	
  
un	
   constructor	
   de	
   emisor	
   de	
   eventos	
   con	
   todos	
  
los	
   métodos	
   necesarios	
   para	
   el	
   registro,	
  
desregistro	
  y	
  propagación	
  de	
  eventos.	
  	
  
Arquitecturas	
  Distribuidas	
  
UQl	
  
Algunos	
  autores	
  uElizan	
  el	
  método	
  inherits	
  de	
  la	
  
librería	
   estándar	
   uEl	
   con	
   el	
   fin	
   de	
   explotar	
   las	
  
capacidades	
  de	
  la	
  librería	
  events	
  por	
  herencia	
  en	
  
lugar	
  de	
  por	
  delegación	
  
Postal	
  
Postal	
   es	
   un	
   bus	
   de	
   comunicaciones	
   que	
  
implementa	
  el	
  patrón	
  PUB-­‐SUB	
  tanto	
  para	
  cliente	
  
como	
   para	
   servidor.	
   Usa	
   expresiones	
   regulares	
  
sobre	
  el	
  Epo	
  de	
  eventos	
  para	
  gesEonar	
  familias	
  y	
  
goza	
  de	
  buena	
  comunidad	
  
Arquitecturas	
  Centralizadas	
  
@javiervelezreye	
  1-­‐30	
  	
  
Modelo	
  de	
  Eventos	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
V.	
  Conclusiones	
  
	
  
El	
   modelo	
   dirigido	
   por	
   eventos	
   ofrece	
   grandes	
  
posibilidades	
  y	
  da	
  respuesta	
  a	
  un	
  abanico	
  nuevo	
  
de	
   problemas	
   que	
   resultan	
   concomitantes	
   con	
  
la	
   programación	
   reac2va	
   y	
   las	
   soluciones	
   de	
  
correlación	
  de	
  eventos.	
  
Aunque	
  este	
  modelo	
  es	
  altamente	
  prometedor	
  
y	
   supone	
   grandes	
   ventajas	
   con	
   respecto	
   al	
   de	
  
paso	
   de	
   con2nuaciones,	
   no	
   deja	
   de	
   tener	
  
detractores	
  que	
  consideran	
  el	
  uso	
  de	
  promesas	
  
un	
  artefacto	
  demasiado	
  ar2ficial	
  e	
  incomodo	
  de	
  
tratar.	
  
Lo	
  Bueno	
   Lo	
  Malo	
  
Desacoplamiento	
  
nominal	
  
Esquemas	
  de	
  
comunicación	
  1:N	
  o	
  N:M	
  
Fácil	
  extensibilidad	
  del	
  sistema	
  
reacQvo	
  por	
  medio	
  de	
  la	
  adición	
  
de	
  nuevos	
  manejadores	
  
Los	
  procesos	
  de	
  coordinación	
  
resultan	
  complicados	
  
La	
  lógica	
  de	
  
secuenciamiento	
  queda	
  
diluida	
  entre	
  los	
  
manejadores	
  
Resulta	
  más	
  invasivo	
  
que	
  otras	
  soluciones	
  
Código	
  di`cil	
  de	
  seguir,	
  mantener	
  
y	
  depurar	
  a	
  medida	
  que	
  crece	
  el	
  
tamaño	
  del	
  problema	
  	
  	
  
Razonamos	
  localmente	
  en	
  
problemas	
  desacoplados	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.veler.reyes@gmail.com	
  
5	
  Modelo	
  de	
  
Promesas	
  
§  Qué	
  es	
  una	
  Promesa	
  
§  Control	
  de	
  Flujo	
  Mediante	
  Promesas	
  
§  Ejemplo	
  
§  Librerías	
  
§  Conclusiones	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
@javiervelezreye	
  1-­‐32	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  Promesa	
  
	
  
Una	
  promesa	
  es	
  una	
  abstracción	
  computacional	
  que	
  representa	
  un	
  compromiso	
  por	
  parte	
  de	
  
la	
  operación	
  no	
  bloqueante	
  invocada	
  de	
  entregar	
  una	
  respuesta	
  al	
  programa	
  llamante	
  cuando	
  
se	
  obtenga	
  un	
  resultado	
  tras	
  su	
  finalización.	
  La	
  promesa	
  es	
  un	
  objeto	
  que	
  expone	
  dos	
  métodos	
  
inyectores	
  then	
  y	
  fail	
  para	
  incluir	
  la	
  lógica	
  de	
  tratamiento	
  en	
  caso	
  de	
  éxito	
  o	
  fracaso.	
  
var promise = div (a, b);
promise.then (function (data) {
console.log (data)
}).fail (function (error) {
console.error (error)
});
La	
   promesa	
   incluye	
   dos	
   funciones,	
   then	
   y	
   fail,	
  
que	
  permiten	
  indicar	
  cómo	
  tratar	
  los	
  resultados	
  
o	
  manejar	
  los	
  errores	
  una	
  vez	
  que	
  la	
  operación	
  
no	
  bloqueante	
  ha	
  terminado	
  
Inyección	
  de	
  manejadores	
  
function div (x, y) {
var result = ...
return <<toPromise (result)>>;
}
Se	
   recupera	
   el	
   control	
   sobre	
   el	
   flujo	
   del	
  
programa.	
   Los	
   proveedores	
   vuelven	
   a	
   devolver	
  
(promesas	
  de)	
  valores	
  y	
  los	
  clientes	
  uElizar	
  esas	
  
(promesas	
  de)	
  valor	
  en	
  una	
  expresión	
  
Comunicación	
  basada	
  en	
  promesas	
  
@javiervelezreye	
  1-­‐33	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  Promesa	
  
	
  
Las	
  promesas	
  responden	
  a	
  un	
  sencillo	
  ciclo	
  de	
  vida	
  que	
  es	
  necesario	
  conocer	
  para	
  operar	
  con	
  
ellas	
  convenientemente.	
  El	
  valor	
  esencial	
  de	
  una	
  promesa	
  reside	
  en	
  2	
  principios.	
  Primero	
  que	
  
la	
  lógica	
  de	
  tratamiento	
  en	
  caso	
  de	
  éxito	
  o	
  fracaso	
  sólo	
  se	
  ejecuta	
  una	
  vez.	
  Y	
  segundo	
  que	
  se	
  
garan2za	
  la	
  ejecución	
  de	
  la	
  lógica	
  de	
  éxito	
  o	
  fracaso	
  aunque	
  la	
  promesa	
  se	
  resuelva	
  antes	
  de	
  
haber	
   inyectado	
   sus	
   manejadores.	
   La	
   promesa	
   espera,	
   si	
   es	
   necesario	
   a	
   disponer	
   de	
   sus	
  
manejadores.	
  
Ciclo	
  de	
  vida	
  de	
  una	
  promesa	
  
Se	
  espera	
  la	
  finalización	
  
del	
  método	
  async	
  
Pending	
  
Fulfilled	
  
Rejected	
  
Resolved	
  
El	
  manejador	
  aún	
  
no	
  se	
  ha	
  ejecutado,	
  
esté	
  inyectado	
  o	
  no	
  
Sebled	
  
El	
  método	
  async	
  ha	
  
terminado	
  con	
  una	
  
respuesta	
  
value	
  
error	
  
then	
  (value)	
  
fail	
  (error)	
  
Se	
  ha	
  ejecutado	
  la	
  
función	
  manejadora	
  
de	
  éxito	
  o	
  de	
  fracaso	
  
@javiervelezreye	
  1-­‐34	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Una	
  Promesa	
  
	
  
Existen	
   diversas	
   formas	
   de	
   obtener	
   promesas	
   que	
   pueden	
   iden2ficarse	
   como	
   patrones	
   de	
  
construcción	
   que	
   aparecen	
   recurrentemente	
   al	
   u2lizar	
   este	
   modelo.	
   A	
   con2nuación	
  
comentamos	
  los	
  más	
  relevantes	
  con	
  ejemplos	
  en	
  la	
  librería	
  Q.	
  
Construcción	
  de	
  Promesas	
  
var promise = getPromise ();
Obtención	
  directa	
  
return Q.fcall (function () {
return value;
});
Invocación	
  funcional	
  
var promise = Q.resolve (value);
Resolución	
  directa	
  
var promise = Q.reject(error);
Rechazo	
  directo	
  
var deferred = Q.defer();
if (error) deferred.reject (error);
if (data) deferred.resolve (data);
return deferred.promise;
Factoría	
  de	
  diferidos	
  
var f = Q.denodeify(fs.readFile);
var f = Q.nfbind (fs.readFile);
Q.nfcall (fs.readFile (...));
Denodificación	
  
@javiervelezreye	
  1-­‐35	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Promesas	
  
	
  
La	
  lógica	
  de	
  control	
  secuencial	
  puede	
  obtenerse	
  mediante	
  el	
  encadenamiento	
  the	
  sucesivas	
  
invocaciones	
  al	
  método	
  de	
  inyección	
  then.	
  Este	
  encadenamiento	
  provoca	
  un	
  comportamiento	
  
secuencial	
  puesto	
  que	
  cada	
  función	
  then	
  genera,	
  al	
  retornar,	
  una	
  promesa	
  que	
  encapsula	
  el	
  
valor	
  devuelto	
  (a	
  menos	
  que	
  éste	
  sea	
  ya	
  una	
  promesa)	
  lo	
  que	
  obliga	
  a	
  mantener	
  el	
  orden.	
  
A.	
  Secuenciamiento	
  
Q.resolve (2)
.then (function (value) {
return value - 1;
})
.then (function (value) {
return value - 1;
})
.then (function (value) {
if (value===0) throw Error ();
return (8 / value);
})
.then (function (value) {
return value + 1;
})
.fail (function (error) {
console.log (error);
});
2
1
0
error	
  
@javiervelezreye	
  1-­‐36	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Promesas	
  
	
  
Al	
  igual	
  que	
  ocurría	
  en	
  el	
  modelo	
  de	
  paso	
  de	
  con2nuidades,	
  la	
  paralelización	
  se	
  consigue	
  por	
  
invocación	
  directa	
  de	
  las	
  operaciones,	
  ya	
  que	
  éstas	
  2enen	
  un	
  comportamiento	
  no	
  bloqueante.	
  
En	
   este	
   modelo	
   sin	
   embargo	
   la	
   programación	
   resulta	
   más	
   natural	
   ya	
   que	
   cada	
   operación	
  
devuelve	
  un	
  valor	
  de	
  retorno	
  instantáneamente	
  en	
  forma	
  de	
  promesa.	
  
B.	
  Paralelización	
  
var r1 = add(2, 3);
var r2 = sub(3, 4);
add	
  (2,	
  3)	
   sub(3,	
  4)	
  
function doParallel(fns, params) {
var promises = [];
for (var index = 0; index < fns.length; index ++) {
var p = Q.fapply (fns[index], params[index]);
promises.push (p);
}
return promises;
}
var promises = doParallel ([add, sub], [[2,3],[4,5]]);
var r1 = Q.fcall (add, 2, 3);
var r2 = Q.fcall (sub, 3, 4);
@javiervelezreye	
  1-­‐37	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Promesas	
  
	
  
Dado	
  que	
  disponemos	
  de	
  los	
  resultados	
  potenciales	
  en	
  forma	
  de	
  promesas	
  es	
  fácil	
  ar2cular	
  
sobre	
  ellos	
  polí2cas	
  de	
  sincronización.	
  El	
  método	
  all	
  genera	
  una	
  promesa	
  que	
  toma	
  una	
  array	
  
de	
  promesas	
  y	
  se	
  resuelve	
  a	
  un	
  array	
  de	
  valores	
  cuando	
  todas	
  las	
  promesas	
  se	
  han	
  resuelto.	
  Si	
  
hay	
   fallo	
   se	
   devuelve	
   el	
   de	
   la	
   primera	
   promesa	
   del	
   array	
   en	
   fallo.	
   allSebled	
   por	
   su	
   parte	
  
resuelve	
  cuando	
  todas	
  las	
  promesas	
  estan	
  en	
  senled.	
  Finalmente,	
  spread	
  es	
  la	
  versión	
  en	
  array	
  
del	
  método	
  then.	
  
C.	
  Sincronización	
  
var promises = doParallel ([add, sub], [[2,3],[4,5]]);
Q.all (promises).then (function (values) {
console.log (values);
});
add	
  (2,	
  3)	
   sub	
  (4,	
  5)	
  
var promises = doParallel ([mul, div], [[2,3],[4,0]]);
Q.allSettled (promises).spread (function (vMul, vDiv) {
if (vMul.state === "fulfilled") console.log (vMul.value);
if (vDiv.state === "fulfilled") console.log (vDiv.value);
});
console	
  
@javiervelezreye	
  1-­‐38	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
III.	
  Ejemplo	
  
	
  
Dada	
   una	
   colección	
   de	
   ficheros,	
   leer	
   su	
  
contenido	
  y	
  contabilizar	
  el	
  número	
  total	
  de	
  
ocurrencias	
   de	
   cada	
   carácter	
   contenido	
  
dentro	
  de	
  los	
  mismos	
  
	
  
1.  Leer	
  cada	
  fichero	
  en	
  paralelo	
  
2.  Contabilizar	
  su	
  número	
  de	
  ocurrencias	
  
3.  Sumar	
  los	
  resultados	
  
init	
  
read	
  
count	
  
add	
  
Paralelización	
  
Secuenciamiento	
  
Sincronización	
  
Se	
  lanzan	
  a	
  ejecución	
  de	
  forma	
  iteraEva	
  
todas	
  las	
  ramas	
  paralelas	
  y	
  se	
  construye	
  
un	
  array	
  de	
  promesas	
  para	
  su	
  posterior	
  
sincronización.	
  	
  
El	
  secuenciamiento	
  consiste	
  meramente	
  
en	
  encadenar	
  las	
  funciones	
  de	
  lectura	
  y	
  
conteo	
  con	
  dos	
  métodos	
  then.	
  
Se	
  recogen	
  las	
  promesas	
  que	
  resultan	
  de	
  cada	
  rama	
  
secuencial	
   en	
   un	
   array	
   para	
   poderlas	
   sincronizar	
  
haciendo	
  uso	
  del	
  método	
  all.	
  
Promises.js	
  
@javiervelezreye	
  1-­‐39	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
IV.	
  Librerías	
  
	
  
Existen	
  varias	
  librerías	
  que	
  implementan	
  el	
  
modelo	
   de	
   promesas.	
   Tal	
   vez	
   la	
   de	
   mayor	
  
comunidad	
  es	
  Q,	
  aunque	
  otras	
  como	
  When	
  
o	
   RSVP,	
   también	
   gozan	
   de	
   bastante	
  
tracción.	
   En	
   aras	
   a	
   disponer	
   de	
   un	
   marco	
  
compara2vo	
  de	
  referencia	
  se	
  ha	
  definido	
  el	
  
estándar	
  Promises	
  A+	
  que	
  rige	
  todas	
  todas	
  
las	
  librerías	
  con	
  objetos	
  then-­‐able.	
  
@javiervelezreye	
  1-­‐40	
  	
  
Modelo	
  de	
  Promesas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
V.	
  Conclusiones	
  
	
  
Hemos	
  recuperado	
  en	
  gran	
  parte	
  el	
  control	
  de	
  
flujo	
  del	
  programa	
  de	
  manera	
  que	
  el	
  esquema	
  
de	
   desarrollo	
   de	
   aplicaciones	
   asíncronas	
  
basadas	
   en	
   promesas	
   se	
   parece	
   algo	
   más	
   al	
  
es2lo	
   secuencial	
   	
   manteniendo	
   su	
   carácter	
   no	
  
bloqueante.	
  
Aunque	
  este	
  modelo	
  es	
  altamente	
  prometedor	
  
y	
   supone	
   grandes	
   ventajas	
   con	
   respecto	
   al	
   de	
  
paso	
   de	
   con2nuaciones,	
   no	
   deja	
   de	
   tener	
  
detractores	
  que	
  consideran	
  el	
  uso	
  de	
  promesas	
  
un	
  artefacto	
  demasiado	
  ar2ficial	
  e	
  incomodo	
  de	
  
tratar.	
  
Lo	
  Bueno	
   Lo	
  Malo	
  
Recuperamos	
  el	
  return	
  y	
  
la	
  asignación	
  
APIs	
  más	
  limpias	
  sin	
  
métodos	
  de	
  callback	
  
(callback	
  en	
  cliente)	
  
Estructura	
  del	
  programa	
  
más	
  similar	
  a	
  la	
  
programación	
  secuencial	
  	
  
No	
  deja	
  de	
  ser	
  necesario	
  
inyectar	
  funciones	
  manejadoras	
  
de	
  éxito	
  y	
  error	
  
Resulta	
  di`cil	
  depurar	
  
hasta	
  que	
  las	
  promesas	
  
no	
  se	
  han	
  resuelto	
  	
  
Resulta	
  más	
  invasivo	
  
generar	
  APIs	
  que	
  
consuman	
  y	
  generen	
  
promesas	
  Es	
  imprescindible	
  hacer	
  
uso	
  de	
  librerías	
  de	
  
terceros	
  para	
  gesQonar	
  
las	
  promesas	
  
Razonamos	
  con	
  promesas	
  
como	
  valores	
  de	
  futuro	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.veler.reyes@gmail.com	
  
6	
  Modelo	
  de	
  
Generadores	
  
§  Qué	
  es	
  un	
  Generador	
  
§  Los	
  Generadores	
  como	
  Modelo	
  de	
  Asincronía	
  
§  Control	
  de	
  Flujo	
  Mediante	
  Generadores	
  
§  Ejemplo	
  
§  Librerías	
  
§  Conclusiones	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
@javiervelezreye	
  1-­‐42	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
I.	
  Qué	
  es	
  Un	
  Generador	
  
	
  
Imagina	
  un	
  procedimiento	
  que	
  pudiera	
  ser	
  interrumpido	
  en	
  su	
  ejecución	
  en	
  cualquier	
  punto	
  
antes	
  de	
  su	
  terminación	
  para	
  devolver	
  el	
  control	
  al	
  programa	
  llamante	
  y	
  más	
  adelante	
  éste	
  
volver	
  a	
  cederle	
  el	
  control	
  para	
  que	
  con2núe	
  justo	
  en	
  el	
  punto	
  donde	
  fue	
  interrumpido	
  y	
  con	
  el	
  
estado	
  que	
  tenía.	
  Eso	
  es	
  un	
  generador.	
  Antes	
  de	
  ver	
  su	
  aplicación	
  en	
  modelos	
  de	
  asincronía	
  
veamos	
  cómo	
  funciona	
  y	
  cuál	
  puede	
  ser	
  su	
  aplicabilidad	
  prác2ca.	
  	
  
function* fibonacci () {
var a = 1;
var b = 0;
var aux;
while (true){
aux = a + b;
a = b;
b = aux;
var reset = yield b;
if (reset){
a = 1;
b = 0;
}
}
}
var fib = fibonacci() {
for (var i=0; i<10; i++) {
var f = fib.next();
console.log(f.value);
}
}
console.log (fib.next().value);
console.log (fib.next().value);
console.log (fib.next(true).value);
console.log (fib.next().value);
console.log (fib.next().value);
Yield	
  
Suspende	
   la	
   ejecución	
  
y	
  devuelve	
  b	
  
Reset	
  
ObEene	
   como	
   retorno	
  
el	
  argumento	
  de	
  next	
  
Next	
  
Inicia	
  o	
  reanuda	
  la	
  ejecución	
  
hasta	
  el	
  siguiente	
  next	
  
{	
  value:	
  n,	
  
	
  	
  done:	
  false	
  }	
  
Generators.fib.js	
  
Requiere	
  
§  NodeJS	
  >	
  0.11	
  	
  
§  flag	
  -­‐-­‐harmony	
  
@javiervelezreye	
  1-­‐43	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Los	
  Generadores	
  como	
  Modelo	
  de	
  Asincronía	
  
JS	
  es	
  un	
  lenguaje	
  de	
  orden	
  superior	
  lo	
  que	
  implica	
  que	
  trata	
  a	
  las	
  funciones	
  como	
  cualquier	
  
otro	
  2po	
  de	
  dato.	
  Pueden	
  asignarse	
  a	
  variables,	
  pasarse	
  como	
  parámetros	
  o	
  devolverse	
  como	
  
resultado.	
  Lo	
  bueno	
  de	
  esto	
  úl2mo	
  es	
  que	
  una	
  función	
  que	
  es	
  devuelta	
  como	
  resultado	
  de	
  
invocar	
  a	
  otra	
  función	
  man2ene	
  el	
  contexto	
  de	
  variables	
  definido	
  dentro	
  de	
  esta	
  úl2ma	
  para	
  su	
  
ejecución.	
  Veamos	
  un	
  ejemplo:	
  
¿Qué	
  es	
  Una	
  Clausura?	
  
function Logger(cls) {
var pre = ‘Logger’;
var post = ‘...’;
return function (message) {
console.log ('%s[%s] - [%s]%s',
pre, cls, message, post);
}
}
var log = Logger (‘Generators’);
log(‘starting’);
log(1234);
log(‘end’);
function (message) {...}
pre post cls
clausura	
  
Clausura	
  
Al	
   devolver	
   una	
   función	
   hacia	
   fuera	
   del	
  
ámbito	
  de	
  definición	
  se	
  manEene	
  el	
  contexto	
  
de	
  variables	
  y	
  parámetros	
  que	
  dicha	
  función	
  
Eene	
   dentro,	
   de	
   forma	
   trasparente.	
   A	
   ese	
  
contexto	
  se	
  le	
  llama	
  clausura	
  
@javiervelezreye	
  1-­‐44	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Los	
  Generadores	
  como	
  Modelo	
  de	
  Asincronía	
  
En	
  muchas	
  ocasiones	
  resulta	
  conveniente	
  conver2r	
  una	
  función	
  de	
  n	
  parámetros	
  en	
  otra	
  que	
  
resuelve	
  el	
  primer	
  parámetro	
  y	
  devuelve	
  como	
  resultado	
  otra	
  función	
  con	
  n-­‐1	
  parámetros.	
  	
  A	
  
esto	
  se	
  le	
  llama	
  evaluación	
  parcial	
  de	
  una	
  función.	
  Cuando	
  la	
  evaluación	
  parcial	
  se	
  repite	
  para	
  
cada	
  parámetro	
  de	
  la	
  función	
  el	
  proceso	
  se	
  llama	
  currificación.	
  
function add(a, b) {
return a + b;
}
¿Qué	
  es	
  Evaluación	
  Parcial	
  de	
  una	
  Función?	
  
function add(a) {
return function (b) {
return a + b;
}
}
var r = add(3, 2);
var r1 = add(3)(2);
var inc = add(1);
var r2 = inc(5);
Evaluación	
  total	
  
En	
   la	
   evaluación	
   total	
   el	
   cliente	
  
debe	
   esperar	
   hasta	
   obtener	
   todos	
  
los	
   parámetros	
   actuales	
   (3	
   y	
   2)	
  
para	
  poder	
  invocar	
  a	
  la	
  función	
  
Evaluación	
  parcial	
  
En	
   la	
   evaluación	
   parcial	
   cada	
   parámetro	
   (por	
   orden)	
  
puede	
  ser	
  resuelto	
  de	
  manera	
  independiente	
  en	
  sucesivas	
  
evaluaciones.	
  Esto,	
  como	
  veremos,	
  nos	
  da	
  la	
  oportunidad	
  
de	
  conseguir	
  que	
  sean	
  disEntos	
  clientes	
  los	
  que	
  realicen	
  
cada	
  evaluación	
  parcial	
  
@javiervelezreye	
  1-­‐45	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Los	
  Generadores	
  como	
  Modelo	
  de	
  Asincronía	
  
En	
  términos	
  generales	
  un	
  Thunk	
  es	
  una	
  abstracción	
  computacional	
  que	
  sirve	
  de	
  vehículo	
  para	
  
comunicar	
  información	
  entre	
  dos	
  frameworks	
  diferentes.	
  En	
  nuestro	
  caso	
  queremos	
  pasar	
  de	
  
un	
  modelo	
  de	
  invocación	
  basado	
  en	
  con2nuaciones	
  en	
  otro	
  que	
  las	
  oculte.	
  Haciendo	
  uso	
  de	
  los	
  
dos	
  conceptos	
  anteriores	
  –	
  clausuras	
  y	
  evaluación	
  parcial	
  –	
  proponemos	
  construir	
  el	
  siguiente	
  
thunk.	
  	
  
function add(a, b, callback){
callback (null, x + y);
}
¿Qué	
  es	
  un	
  Thunk?	
  
function add(a, b) {
return function (callback) {
callback (null, x + y);
}
}
add(3, 2, function(error, data){
console.log (data);
}); var r = add(3, 2);
r(function (error, data) {
console.log (data);
});
Thunk	
  
Nuestros	
   thunks	
   devuelven	
   funciones	
   que	
   esperan	
  
manejadores	
   como	
   parámetros.	
   De	
   esta	
   manera	
  
ocultamos	
  el	
  manejador	
  en	
  la	
  primera	
  evaluación	
  parcial:	
  
add	
  (2,3);	
  	
  
@javiervelezreye	
  1-­‐46	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Los	
  Generadores	
  como	
  Modelo	
  de	
  Asincronía	
  
Podemos	
  construir	
  un	
  framework	
  sobre	
  el	
  que	
  escribir	
  generadores	
  que	
  devuelvan	
  thunks	
  (con	
  
yield)	
  lo	
  que	
  simplifica	
  el	
  código	
  cliente.	
  El	
  framework	
  por	
  su	
  parte	
  va	
  secuenciando	
  el	
  código	
  
del	
   generador	
   (con	
   next)	
   y	
   se	
   interpone	
   para	
   resolver	
   de	
   forma	
   transparente	
   la	
   segunda	
  
evaluación	
  parcial	
  que	
  corresponde	
  con	
  la	
  función	
  de	
  callback.	
  Su	
  labor	
  consiste	
  en	
  extraer	
  los	
  
datos	
  del	
  callback	
  y	
  retornarlos	
  al	
  generador	
  para	
  que	
  éste	
  los	
  obtenga	
  como	
  una	
  variable	
  local	
  
co (function* (){
var r1 = yield add (2,3);
var r2 = yield sub (3,4);
console.log (r1, r2);
})();
Generadores	
  y	
  Thunks	
  
Cliente	
  
var co = function (codeGn) {
var code = codeGn ();
function step(thunk) {
if (thunk.done) return thunk.value;
else {
thunk.value (function (error, data){
step(code.next (data));
});
}
}
return function () {
step(code.next ());
};
};
Framework	
  
Generators.co.js	
  
Requiere	
  
§  NodeJS	
  >	
  0.11	
  	
  
§  flag	
  -­‐-­‐harmony	
  
@javiervelezreye	
  1-­‐47	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Generadores	
  
	
  
De	
   lo	
   que	
   hemos	
   visto,	
   el	
   uso	
   de	
   yield	
   dentro	
   de	
   un	
   generador	
   evaluado	
   por	
   nuestro	
  
framework	
   asíncrono	
   permite	
   a	
   éste	
   interponerse	
   para	
   capturar	
   la	
   función	
   de	
   callback	
   y	
  
resolver	
   un	
   thunk	
   en	
   su	
   valor	
   equivalente.	
   De	
   ello	
   se	
   deduce	
   que	
   cada	
   vez	
   que	
   queramos	
  
secuenciar	
  operaciones	
  sólo	
  tenemos	
  que	
  interponer	
  yield	
  antes	
  de	
  la	
  operación.	
  
A.	
  Secuenciamiento	
  
co(function* (){
var r1 = yield mul(2,3);
var r2 = yield div(3,4);
var r3 = yield add(4,5);
console.log (r1, r2, r3);
})();
mul	
  (2,	
  3)	
  
div	
  (3,	
  4)	
  
add	
  (4,	
  5)	
  
2	
  *	
  3	
  /	
  4	
  +	
  5	
  	
  	
  
Yield	
  en	
  secuencia	
  
Cada	
   yield	
   puede	
   leerse	
   como	
   un	
   paso	
   dentro	
   de	
   una	
  
secuencia	
  de	
  operaciones.	
  Cada	
  operación	
  no	
  bloqueante	
  
(mul,	
  div	
  y	
  add)	
  devuelve	
  un	
  thunk	
  que	
  el	
  framework,	
  co,	
  
recoge	
  para	
  resolver	
  a	
  un	
  valor	
  y	
  devolverlo	
  al	
  contexto	
  
del	
  generador	
  como	
  una	
  variable	
  local	
  (r1,	
  r2	
  y	
  r3)	
  	
  
@javiervelezreye	
  1-­‐48	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
II.	
  Control	
  de	
  Flujo	
  Mediante	
  Generadores	
  
	
  
Razonablemente	
  todas	
  aquellas	
  operaciones	
  no	
  bloqueantes	
  que	
  no	
  sean	
  intercedidas	
  por	
  el	
  
framework	
  a	
  través	
  de	
  la	
  cláusula	
  yield	
  darán	
  lugar	
  a	
  esquemas	
  de	
  ejecución	
  paralelos.	
  Es	
  una	
  
prác2ca	
   común	
   agrupar	
   estas	
   invocaciones	
   en	
   colecciones	
   (arrays	
   u	
   objetos)	
   para	
  
posteriormente	
  hacer	
  la	
  resolución	
  de	
  thunks	
  a	
  valores.	
  
B.	
  Paralelización	
  &	
  C.	
  Sincronización	
  
co(function* (){
var r1 = add(2,3);
var r2 = sub(3,4);
var r = yield [r1, r2];
console.log (r);
})();
Array	
  de	
  thunks	
  
Cada	
   operación	
   no	
   bloqueante	
   aquí	
   es	
   evaluada	
   sin	
   la	
  
clausula	
  yield	
  con	
  lo	
  que	
  lo	
  que	
  se	
  obEene	
  en	
  r1	
  y	
  r2	
  son	
  
dos	
  thunks	
  ejecutados	
  en	
  paralelo	
  
add	
  (2,	
  3)	
   sub(3,	
  4)	
  
Yield	
  de	
  Array	
  
Yield	
   aplicado	
   a	
   un	
   array	
   se	
   evalúa	
   como	
   el	
  
array	
  de	
  los	
  yields.	
  Yield	
  aplicado	
  a	
  un	
  objeto	
  se	
  
evalúa	
  como	
  el	
  yield	
  aplicado	
  a	
  cada	
  propiedad	
  
del	
  objeto.	
  De	
  esta	
  forma,	
  este	
  yield	
  convierte	
  el	
  
array	
  de	
  thunks	
  en	
  un	
  array	
  de	
  valores	
  
@javiervelezreye	
  1-­‐49	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
III.	
  Ejemplo	
  
	
  
Dada	
   una	
   colección	
   de	
   ficheros,	
   leer	
   su	
  
contenido	
  y	
  contabilizar	
  el	
  número	
  total	
  de	
  
ocurrencias	
   de	
   cada	
   carácter	
   contenido	
  
dentro	
  de	
  los	
  mismos	
  
	
  
1.  Leer	
  cada	
  fichero	
  en	
  paralelo	
  
2.  Contabilizar	
  su	
  número	
  de	
  ocurrencias	
  
3.  Sumar	
  los	
  resultados	
  
init	
  
read	
  
count	
  
add	
  
Paralelización	
  
Secuenciamiento	
  
Sincronización	
  
Mediante	
   un	
   bucle,	
   se	
   construye	
   un	
  
array	
   de	
   generadores	
   para	
   cada	
   rama	
  
paralela	
  
Se	
   construye	
   un	
   generador	
   capaz	
   de	
  
secuenciar	
  las	
  dos	
  operaciones	
  –	
  read	
  y	
  
count	
   –	
   que	
   conforman	
   cada	
   rama	
  
paralela	
  
Se	
  hace	
  un	
  yield	
  de	
  los	
  resultados	
  para	
  sincronizar	
  y	
  
se	
   invoca	
   a	
   add	
   para	
   obtener	
   los	
   totales,	
   que	
   se	
  
devuelven	
   al	
   cliente	
   con	
   otro	
   yield	
   ya	
   que	
   add	
  
también	
  es	
  no	
  bloqueante	
  
Generators.js	
  
Requiere	
  
§  NodeJS	
  >	
  0.11	
  	
  
§  flag	
  -­‐-­‐harmony	
  
@javiervelezreye	
  1-­‐50	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
IV.	
  Librerías	
  
	
  
Aunque	
   existen	
   varias	
   librerías	
   que	
   dan	
   soporte	
   a	
   esta	
   idea	
   –	
   ar2cular	
   un	
   framework	
   de	
  
soporte	
   a	
   la	
   programación	
   asíncrona	
   basado	
   en	
   generadores	
   –	
   la	
   que	
   goza	
   de	
   mayor	
  
comunidad	
   es	
   co.	
   En	
   torno	
   a	
   ella	
   se	
   pueden	
   encontrar	
   una	
   amplia	
   colección	
   de	
   librerías	
  
u2litarias	
  vinculadas	
  que	
  conforman	
  el	
  ecosistema	
  de	
  co.	
  
Co	
  
Ecosistema	
  Co*	
  
Thunkify	
  
El	
  framework	
  de	
  programación	
  asíncrona	
  basado	
  
en	
   generadores	
   con	
   mayor	
   aceptación.	
   Co	
   no	
  
sólo	
   es	
   capaz	
   de	
   operar	
   con	
   Thunks	
   como	
  
abstracción	
  vehicular	
  sino	
  que	
  también	
  funciona	
  
con	
   promesas,	
   funciones,	
   generadores	
   y	
  
funciones	
  generadoras.	
  
Librerías	
   específicas,	
   adaptadores	
   de	
   APIs,	
  
servidores,	
   funciones	
   uElitarias	
   de	
   control	
   de	
  
flujo…	
   Todo	
   un	
   ecosistema	
   de	
   herramientas	
  
para	
   programar	
   dentro	
   del	
   framework	
   co.	
   Se	
  
puede	
  ver	
  una	
  relación	
  exhausEva	
  en	
  la	
  wiki	
  de	
  
Co	
  accesible	
  desde	
  github	
  	
  	
  
Se	
  trata	
  de	
  una	
  simple	
  función	
  que	
  convierte	
  
a	
   un	
   thunk	
   cualquier	
   función	
   definida	
   de	
  
acuerdo	
  al	
  modelo	
  de	
  paso	
  de	
  conEnuidades	
  
estandarizado	
  por	
  Node	
  JS.	
  
@javiervelezreye	
  1-­‐51	
  	
  
Modelo	
  de	
  Generadores	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
V.	
  Conclusiones	
  
	
  
La	
   programación	
   asíncrona	
   basada	
   en	
  
generadores	
  es,	
  tal	
  vez,	
  la	
  opción	
  que	
  mejor	
  ha	
  
conseguido	
  acercar	
  la	
  experiencia	
  de	
  desarrollo	
  
a	
  la	
  programación	
  secuencial.	
  A	
  la	
  fecha	
  de	
  esta	
  
charla	
   aún	
   es	
   pronto	
   para	
   saber	
   si	
   será	
  
ampliamente	
  aceptada	
  por	
  la	
  comunidad	
  o	
  no.	
  
El	
   modelo	
   de	
   programación	
   asíncrona	
   basada	
  
en	
   generadores	
   sigue	
   teniendo	
   inconvenientes	
  
serios	
   relacionados	
   con	
   la	
   invasividad	
   del	
  
framework	
   y	
   el	
   uso	
   permanente	
   de	
   clausulas	
  
yield	
  para	
  ar2cular	
  el	
  manejo	
  del	
  control	
  flujo.	
  	
  
Lo	
  Bueno	
   Lo	
  Malo	
  
Esquema	
  de	
  
programación	
  similar	
  al	
  
secuencial	
  
Transparencia	
  en	
  los	
  
procesos	
  de	
  gesQón	
  de	
  
conQnuaciones	
  
Curva	
  de	
  aprendizaje	
  corta.	
  Con	
  
pocas	
  reglas	
  de	
  pulgar	
  se	
  puede	
  
razonar	
  fácilmente	
  en	
  el	
  
modelo	
  	
  
Todo	
  código	
  esta	
  
siempre	
  dentro	
  de	
  un	
  
contexto	
  Co	
   El	
  código	
  está	
  
plagado	
  de	
  yields	
  
¿qué	
  está	
  haciendo	
  Co	
  
por	
  debajo?	
  
ArQficialidad	
  del	
  código.	
  
Perversión	
  del	
  uso	
  de	
  
los	
  yields	
  
@javiervelezreye	
  1-­‐52	
  	
  
Preguntas	
  
Programación	
  Asíncrona	
  en	
  Node	
  JS	
  
Generadores	
  
Promesas	
  Eventos	
  
ConQnuaciones	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.velez.reyes@gmail.com	
  
Javier	
  Vélez	
  Reyes	
  
	
  @javiervelezreye	
  
Javier.velez.reyes@gmail.com	
  
Modelo	
  de	
  Paso	
  de	
  Con,nuaciones,	
  Eventos,	
  
Promesas	
  y	
  Generadores	
  	
  
Programación	
  Asíncrona	
  en	
  
Node	
  JS	
  	
  
Mayo	
  2014	
  

Contenu connexe

Tendances

2 1 vistas arquitectonicas
2 1 vistas arquitectonicas2 1 vistas arquitectonicas
2 1 vistas arquitectonicaslandeta_p
 
Patrones de diseño y frameworks
Patrones de diseño y frameworksPatrones de diseño y frameworks
Patrones de diseño y frameworksDaniel Cam Urquizo
 
Consistencia es un término más amplio que el de integridad
Consistencia es un término más amplio que el de integridadConsistencia es un término más amplio que el de integridad
Consistencia es un término más amplio que el de integridadAngel Sanchez Virgen
 
51036806 proyecto-ejemplo-ingenieria-de-software
51036806 proyecto-ejemplo-ingenieria-de-software51036806 proyecto-ejemplo-ingenieria-de-software
51036806 proyecto-ejemplo-ingenieria-de-softwareMiguel Angel Rodriguez
 
Caracteristicas de un vtp
Caracteristicas de un vtpCaracteristicas de un vtp
Caracteristicas de un vtpErika Vazquez
 
Sistemas distribuidos 2
Sistemas distribuidos 2Sistemas distribuidos 2
Sistemas distribuidos 2Tensor
 
Cuadro comparativo analis y diseño estructurado Y analisis orientado a objetos
Cuadro comparativo analis y diseño estructurado Y analisis orientado a objetosCuadro comparativo analis y diseño estructurado Y analisis orientado a objetos
Cuadro comparativo analis y diseño estructurado Y analisis orientado a objetosemilis
 
PRIMERA PRESENTACION JAVA
PRIMERA PRESENTACION JAVAPRIMERA PRESENTACION JAVA
PRIMERA PRESENTACION JAVANoralma Yanez
 
INDICES EN SQL SERVER
INDICES EN SQL SERVERINDICES EN SQL SERVER
INDICES EN SQL SERVERDarwin Durand
 
FMK Capa de Presentacion
FMK Capa de PresentacionFMK Capa de Presentacion
FMK Capa de Presentacionkaolong
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring FrameworkASG
 

Tendances (20)

2 1 vistas arquitectonicas
2 1 vistas arquitectonicas2 1 vistas arquitectonicas
2 1 vistas arquitectonicas
 
Patrones de diseño y frameworks
Patrones de diseño y frameworksPatrones de diseño y frameworks
Patrones de diseño y frameworks
 
Consistencia es un término más amplio que el de integridad
Consistencia es un término más amplio que el de integridadConsistencia es un término más amplio que el de integridad
Consistencia es un término más amplio que el de integridad
 
51036806 proyecto-ejemplo-ingenieria-de-software
51036806 proyecto-ejemplo-ingenieria-de-software51036806 proyecto-ejemplo-ingenieria-de-software
51036806 proyecto-ejemplo-ingenieria-de-software
 
Recuperación de-datos-en-my sql
Recuperación de-datos-en-my sqlRecuperación de-datos-en-my sql
Recuperación de-datos-en-my sql
 
Caracteristicas de un vtp
Caracteristicas de un vtpCaracteristicas de un vtp
Caracteristicas de un vtp
 
Patron de Arquitectura Broker
Patron de Arquitectura BrokerPatron de Arquitectura Broker
Patron de Arquitectura Broker
 
Sistemas distribuidos 2
Sistemas distribuidos 2Sistemas distribuidos 2
Sistemas distribuidos 2
 
CLASE SWING
CLASE SWING CLASE SWING
CLASE SWING
 
Arquitecturas de software
Arquitecturas de softwareArquitecturas de software
Arquitecturas de software
 
Modelo 4+1
Modelo 4+1Modelo 4+1
Modelo 4+1
 
Cuadro comparativo analis y diseño estructurado Y analisis orientado a objetos
Cuadro comparativo analis y diseño estructurado Y analisis orientado a objetosCuadro comparativo analis y diseño estructurado Y analisis orientado a objetos
Cuadro comparativo analis y diseño estructurado Y analisis orientado a objetos
 
PRIMERA PRESENTACION JAVA
PRIMERA PRESENTACION JAVAPRIMERA PRESENTACION JAVA
PRIMERA PRESENTACION JAVA
 
INDICES EN SQL SERVER
INDICES EN SQL SERVERINDICES EN SQL SERVER
INDICES EN SQL SERVER
 
Patrones diseño y arquitectura
Patrones diseño y arquitecturaPatrones diseño y arquitectura
Patrones diseño y arquitectura
 
ENRUTAMIENTO (REDES)
ENRUTAMIENTO (REDES)ENRUTAMIENTO (REDES)
ENRUTAMIENTO (REDES)
 
Java Spring Framework
Java Spring FrameworkJava Spring Framework
Java Spring Framework
 
FMK Capa de Presentacion
FMK Capa de PresentacionFMK Capa de Presentacion
FMK Capa de Presentacion
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Vista lógica
Vista lógicaVista lógica
Vista lógica
 

En vedette

Taller de Programación Funcional en JavaScript
Taller de Programación Funcional en JavaScriptTaller de Programación Funcional en JavaScript
Taller de Programación Funcional en JavaScriptJavier Vélez Reyes
 
Componentes Web y El Framework Polymer
Componentes Web y El Framework PolymerComponentes Web y El Framework Polymer
Componentes Web y El Framework PolymerJavier Vélez Reyes
 
Curso node.js
Curso node.js Curso node.js
Curso node.js Redradix
 
Curso de javascript y node avanzado
Curso de javascript y node avanzadoCurso de javascript y node avanzado
Curso de javascript y node avanzadobrainybogota
 
Programación Funcional en JavaScript
Programación Funcional en JavaScriptProgramación Funcional en JavaScript
Programación Funcional en JavaScriptJavier Vélez Reyes
 
Estrategias de Programación & Estructuras de Datos
Estrategias de Programación & Estructuras de DatosEstrategias de Programación & Estructuras de Datos
Estrategias de Programación & Estructuras de DatosJavier Vélez Reyes
 
Arquitecturas Reactivas de Streams
Arquitecturas Reactivas de StreamsArquitecturas Reactivas de Streams
Arquitecturas Reactivas de StreamsJavier Vélez Reyes
 
Desarrollo web front-end con TypeScript, Angular 2 e Ionic
Desarrollo web front-end con TypeScript, Angular 2 e IonicDesarrollo web front-end con TypeScript, Angular 2 e Ionic
Desarrollo web front-end con TypeScript, Angular 2 e IonicMicael Gallego
 
TypeScript - Angular 2 - ionic 2
TypeScript - Angular 2 - ionic 2TypeScript - Angular 2 - ionic 2
TypeScript - Angular 2 - ionic 2Micael Gallego
 
Creación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y ExpressCreación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y Expressbetabeers
 
SEO i SEM głównymi kanałami promocji
SEO i SEM głównymi kanałami promocjiSEO i SEM głównymi kanałami promocji
SEO i SEM głównymi kanałami promocjiSEMSTORM
 
Integrating online and offline marketing for a sports brand
Integrating online and offline marketing for a sports brandIntegrating online and offline marketing for a sports brand
Integrating online and offline marketing for a sports brandRebecca Caroe
 
Primera Comisión de expertos en COPLEF Madrid
Primera Comisión de expertos en COPLEF MadridPrimera Comisión de expertos en COPLEF Madrid
Primera Comisión de expertos en COPLEF MadridCOPLEF Madrid
 

En vedette (20)

Taller de Programación Funcional en JavaScript
Taller de Programación Funcional en JavaScriptTaller de Programación Funcional en JavaScript
Taller de Programación Funcional en JavaScript
 
Procesadores de Lenguajes I
Procesadores de Lenguajes IProcesadores de Lenguajes I
Procesadores de Lenguajes I
 
Componentes Web y El Framework Polymer
Componentes Web y El Framework PolymerComponentes Web y El Framework Polymer
Componentes Web y El Framework Polymer
 
Procesadores de Lenguajes II
Procesadores de Lenguajes IIProcesadores de Lenguajes II
Procesadores de Lenguajes II
 
Curso node.js
Curso node.js Curso node.js
Curso node.js
 
Curso de javascript y node avanzado
Curso de javascript y node avanzadoCurso de javascript y node avanzado
Curso de javascript y node avanzado
 
Servidor API REST con Node.js
Servidor API REST con Node.jsServidor API REST con Node.js
Servidor API REST con Node.js
 
Programación Funcional en JavaScript
Programación Funcional en JavaScriptProgramación Funcional en JavaScript
Programación Funcional en JavaScript
 
Estrategias de Programación & Estructuras de Datos
Estrategias de Programación & Estructuras de DatosEstrategias de Programación & Estructuras de Datos
Estrategias de Programación & Estructuras de Datos
 
El Proyecto Polymer
El Proyecto PolymerEl Proyecto Polymer
El Proyecto Polymer
 
Introducción a Node.js
Introducción a Node.jsIntroducción a Node.js
Introducción a Node.js
 
Arquitecturas Reactivas de Streams
Arquitecturas Reactivas de StreamsArquitecturas Reactivas de Streams
Arquitecturas Reactivas de Streams
 
Desarrollo web front-end con TypeScript, Angular 2 e Ionic
Desarrollo web front-end con TypeScript, Angular 2 e IonicDesarrollo web front-end con TypeScript, Angular 2 e Ionic
Desarrollo web front-end con TypeScript, Angular 2 e Ionic
 
TypeScript - Angular 2 - ionic 2
TypeScript - Angular 2 - ionic 2TypeScript - Angular 2 - ionic 2
TypeScript - Angular 2 - ionic 2
 
Creación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y ExpressCreación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y Express
 
ES6 generators
ES6 generatorsES6 generators
ES6 generators
 
Sistemas operativos moviles
Sistemas operativos movilesSistemas operativos moviles
Sistemas operativos moviles
 
SEO i SEM głównymi kanałami promocji
SEO i SEM głównymi kanałami promocjiSEO i SEM głównymi kanałami promocji
SEO i SEM głównymi kanałami promocji
 
Integrating online and offline marketing for a sports brand
Integrating online and offline marketing for a sports brandIntegrating online and offline marketing for a sports brand
Integrating online and offline marketing for a sports brand
 
Primera Comisión de expertos en COPLEF Madrid
Primera Comisión de expertos en COPLEF MadridPrimera Comisión de expertos en COPLEF Madrid
Primera Comisión de expertos en COPLEF Madrid
 

Similaire à Programación Asíncrona en Node JS

Similaire à Programación Asíncrona en Node JS (20)

Seti7 ocw
Seti7 ocwSeti7 ocw
Seti7 ocw
 
Orquestando microservicios como lo hace Netflix
Orquestando microservicios como lo hace NetflixOrquestando microservicios como lo hace Netflix
Orquestando microservicios como lo hace Netflix
 
Dpss u3 a2_paov
Dpss u3 a2_paovDpss u3 a2_paov
Dpss u3 a2_paov
 
Manual practicassd
Manual practicassdManual practicassd
Manual practicassd
 
Unidad 2
Unidad 2Unidad 2
Unidad 2
 
Expo modelocascada
Expo modelocascadaExpo modelocascada
Expo modelocascada
 
(Inmer)La Ingenieria de Software
(Inmer)La Ingenieria de Software(Inmer)La Ingenieria de Software
(Inmer)La Ingenieria de Software
 
Programación Modular y Estructyrada
Programación Modular y EstructyradaProgramación Modular y Estructyrada
Programación Modular y Estructyrada
 
Ensayo de software
Ensayo de softwareEnsayo de software
Ensayo de software
 
Rup (iteraciones)
Rup (iteraciones)Rup (iteraciones)
Rup (iteraciones)
 
Modelo cascada
Modelo cascadaModelo cascada
Modelo cascada
 
Expo modelocascada
Expo modelocascadaExpo modelocascada
Expo modelocascada
 
Apuntes
ApuntesApuntes
Apuntes
 
Técnicas de programación estructurada
Técnicas de programación estructuradaTécnicas de programación estructurada
Técnicas de programación estructurada
 
Diseño de programas
Diseño de programasDiseño de programas
Diseño de programas
 
Ensayo Software
Ensayo SoftwareEnsayo Software
Ensayo Software
 
Unidad III-Programación Modular-introducción al lenguaje programable.pdf
Unidad III-Programación Modular-introducción al lenguaje programable.pdfUnidad III-Programación Modular-introducción al lenguaje programable.pdf
Unidad III-Programación Modular-introducción al lenguaje programable.pdf
 
Modelos de desarrollo de software
Modelos de desarrollo de softwareModelos de desarrollo de software
Modelos de desarrollo de software
 
Teoria de sistema Venta y reparacion de equipos
Teoria de sistema Venta y reparacion de equipos  Teoria de sistema Venta y reparacion de equipos
Teoria de sistema Venta y reparacion de equipos
 
metodologias cascada vs v
metodologias cascada vs vmetodologias cascada vs v
metodologias cascada vs v
 

Plus de Javier Vélez Reyes

Arquitecturas Dirigidas por la Experiencia
Arquitecturas Dirigidas por la ExperienciaArquitecturas Dirigidas por la Experiencia
Arquitecturas Dirigidas por la ExperienciaJavier Vélez Reyes
 
Modelos de API Para El Diseño de Servicios
Modelos de API Para El Diseño de ServiciosModelos de API Para El Diseño de Servicios
Modelos de API Para El Diseño de ServiciosJavier Vélez Reyes
 
Arquitecturas Adaptativas de Componentes Web
Arquitecturas Adaptativas de Componentes WebArquitecturas Adaptativas de Componentes Web
Arquitecturas Adaptativas de Componentes WebJavier Vélez Reyes
 
El futuro es hoy. Del Nomadismo al Capitalismo Web
El futuro es hoy. Del Nomadismo al Capitalismo WebEl futuro es hoy. Del Nomadismo al Capitalismo Web
El futuro es hoy. Del Nomadismo al Capitalismo WebJavier Vélez Reyes
 
Arquitectura de Componentes Web. Patrones de Acceso a Datos
Arquitectura de Componentes Web. Patrones de Acceso a DatosArquitectura de Componentes Web. Patrones de Acceso a Datos
Arquitectura de Componentes Web. Patrones de Acceso a DatosJavier Vélez Reyes
 
Arquitecturas de Componentes Web. Patrones de Composición
Arquitecturas de Componentes Web. Patrones de ComposiciónArquitecturas de Componentes Web. Patrones de Composición
Arquitecturas de Componentes Web. Patrones de ComposiciónJavier Vélez Reyes
 
Arquitecturas Para La Reutilización en JavaScript
Arquitecturas Para La Reutilización en JavaScriptArquitecturas Para La Reutilización en JavaScript
Arquitecturas Para La Reutilización en JavaScriptJavier Vélez Reyes
 
Metaprogramación Compositiva en JavaScript
Metaprogramación Compositiva en JavaScriptMetaprogramación Compositiva en JavaScript
Metaprogramación Compositiva en JavaScriptJavier Vélez Reyes
 
Principios de Diseño de Componentes Web
Principios de Diseño de Componentes WebPrincipios de Diseño de Componentes Web
Principios de Diseño de Componentes WebJavier Vélez Reyes
 

Plus de Javier Vélez Reyes (11)

Arquitecturas Dirigidas por la Experiencia
Arquitecturas Dirigidas por la ExperienciaArquitecturas Dirigidas por la Experiencia
Arquitecturas Dirigidas por la Experiencia
 
Modelos de API Para El Diseño de Servicios
Modelos de API Para El Diseño de ServiciosModelos de API Para El Diseño de Servicios
Modelos de API Para El Diseño de Servicios
 
Arquitecturas Adaptativas de Componentes Web
Arquitecturas Adaptativas de Componentes WebArquitecturas Adaptativas de Componentes Web
Arquitecturas Adaptativas de Componentes Web
 
El futuro es hoy. Del Nomadismo al Capitalismo Web
El futuro es hoy. Del Nomadismo al Capitalismo WebEl futuro es hoy. Del Nomadismo al Capitalismo Web
El futuro es hoy. Del Nomadismo al Capitalismo Web
 
Arquitectura de Componentes Web. Patrones de Acceso a Datos
Arquitectura de Componentes Web. Patrones de Acceso a DatosArquitectura de Componentes Web. Patrones de Acceso a Datos
Arquitectura de Componentes Web. Patrones de Acceso a Datos
 
Arquitecturas de Componentes Web. Patrones de Composición
Arquitecturas de Componentes Web. Patrones de ComposiciónArquitecturas de Componentes Web. Patrones de Composición
Arquitecturas de Componentes Web. Patrones de Composición
 
Arquitecturas Para La Reutilización en JavaScript
Arquitecturas Para La Reutilización en JavaScriptArquitecturas Para La Reutilización en JavaScript
Arquitecturas Para La Reutilización en JavaScript
 
Metaprogramación en JavaScript
Metaprogramación en JavaScriptMetaprogramación en JavaScript
Metaprogramación en JavaScript
 
La Web Orientada a Componentes
La Web Orientada a ComponentesLa Web Orientada a Componentes
La Web Orientada a Componentes
 
Metaprogramación Compositiva en JavaScript
Metaprogramación Compositiva en JavaScriptMetaprogramación Compositiva en JavaScript
Metaprogramación Compositiva en JavaScript
 
Principios de Diseño de Componentes Web
Principios de Diseño de Componentes WebPrincipios de Diseño de Componentes Web
Principios de Diseño de Componentes Web
 

Programación Asíncrona en Node JS

  • 1. Javier  Vélez  Reyes    @javiervelezreye   Javier.velez.reyes@gmail.com   Modelo  de  Paso  de  Con,nuaciones,  Eventos,   Promesas  y  Generadores     Programación  Asíncrona  en   Node  JS     Mayo  2014  
  • 2. @javiervelezreye  1-­‐2     Presentación   Programación  Asíncrona  en  Node  JS   Licenciado   en   informá2ca   por   la   Universidad   Politécnica   de   Madrid  (UPM)  desde  el  año  2001  y  doctor  en  informá2ca  por  la   Universidad   Nacional   de   Educación   a   Distancia   (UNED)   desde   el   año  2009,  Javier  es  inves2gador  y  está  especializado  en  el  diseño   y   análisis   de   la   colaboración.   Esta   labor   la   compagina   con   ac2vidades  de  evangelización,  consultoría,  mentoring  y  formación   especializada  para  empresas  dentro  del  sector  IT.  Inquieto,  ávido   lector  y  seguidor  cercano  de  las  innovaciones  en  tecnología.   I.  ¿Quién  Soy?     II.  ¿A  Qué  Me  Dedico?     E-­‐learning   Diseño  de  Sistemas  de  Colaboración   Learning  Analy2cs   Gamificación  Colabora2va   Diseño  Instruccional   Desarrollado  Front/Back   Evangelización  Web   Arquitectura  SoZware   Formación  &  Consultoría  IT  
  • 3. Javier  Vélez  Reyes    @javiervelezreye   Javier.veler.reyes@gmail.com   1  Introducción   §  Programación  Secuencial   §  Programación  Asíncrona   §  Modelos  de  Programación  Asíncrona   §  Un  ejemplo   Introducción   Programación  Asíncrona  en  Node  JS  
  • 4. @javiervelezreye  1-­‐4     Introducción   Programación  Asíncrona  en  Node  JS   I.  Programación  Secuencial     Tradicionalmente,   el   modelo   de   ejecución   que   u2lizan   la   mayoría   de   los   lenguajes   y   paradigmas   de   programación   se   corresponde   con   un   tratamiento   secuencial   del   cuerpo   del   programa.  Un  programa  es  entendido  como  una  secuencia  de  instrucciones  que  se  ejecutan   ordenadamente  y  donde  la  ejecución  de  cada  operación  no  da  comienzo  hasta  que  no  termina   la  anterior.   Se  dice  que  las  operaciones  son  bloqueantes  ya   que  bloquean  el  flujo  de  ejecución  del  programa   llamante  impidiendo  que  la  siguiente  instrucción   comience  hasta  que  la  anterior  haya  terminado   Operaciones  bloqueantes   S1   S2   S3   S4   El   programa   se   ejecuta   de   principio   a   fin   respetando   el   orden   correlaEvo   que   cada   instrucción   guarda   con   la   instrucción   anterior  y  siguiente   Ejecución  secuencial   Con   este   esquema   resulta   fácil   razonar   acerca   del   comportamiento   del   programa   si   éste   se   concibe  como  un  proceso  de  transformación  de   estado  reflejado  en  las  variables  a  lo  largo  del   Eempo   Razonamiento  basado  en  estado   E  1   E  2   E  3   E  0  
  • 5. @javiervelezreye  1-­‐5     Introducción   Programación  Asíncrona  en  Node  JS   II.  Programación  Asíncrona     La   programación   asíncrona   establece   la   posibilidad   de   hacer   que   algunas   operaciones   devuelvan   el   control   al   programa   llamante   antes   de   que   hayan   terminado   mientras   siguen   operando   en   segundo   plano.   Esto   agiliza   el   proceso   de   ejecución   y   en   general   permite   aumentar  la  escalabilidad  pero  complica  el  razonamiento  sobre  el  programa.   S1   S2   S3   S4   E  1   E  2’   E  3’   E  0   Ahora  algunas  operaciones  son  no  bloqueantes   ya   que   devuelven   el   control   al   programa   llamante   antes   de   su   terminación   mientras   siguen  ejecutando  en  segundo  plano   Operaciones  no  bloqueantes   La   falta   de   secuencialidad   estricta   en   la   ejecución   del   programa   hace   diOcil   determinar   el  estado  al  comienzo  de  cada  operación   Imposible  razonar  sobre  el  estado   Ya   no   se   manEene   el   orden   secuencial   puesto   la   ejecución   de   la   instrucción  que  sigue  a  un  operación   no   bloqueante   se   adelanta   antes   de   que   dicha   no   bloqueante   haya   finalizado   Ejecución  no  secuencial   La   asincronía   permite   que   los   siguientes   procesos   en   espera   adelanten  su  ejecución   Aumento  de  la  escalabilidad  
  • 6. @javiervelezreye  1-­‐6     Introducción   Programación  Asíncrona  en  Node  JS   II.  Programación  Asíncrona     La  programación  asíncrona    resulta  ventajosa  ya   que   aumenta   el   throughput   soportado.   Esta   ventaja  le  está  haciendo  coger  mucha  tracción   dada   la   demanda   de   sistemas   de   alta   escalabilidad  que  se  requieren  en  Internet.   S1   S2  S3   S4   El   principal   problema   de   la   programación   asíncrona   se   refiere   a   cómo   dar   con2nuidad   a   las   operaciones   no   bloqueantes   del   algoritmo   una  vez  que  éstas  han  terminado  su  ejecución.   Lo  Bueno   Lo  Malo   Startup   Shutdown   Cola  de  Procesos   entrantes   ¿cómo  conEnuamos?  ¿cómo   recuperamos  el  estado  en   este  punto?  ¿cómo  obtengo   los  resultados?  
  • 7. @javiervelezreye  1-­‐7     Introducción   Programación  Asíncrona  en  Node  JS   III.  Modelos  de  Programación  Asíncrona     Es  el  modelo  de  asincronía  definido  dentro  de   Node   JS.   Cada   función   recibe   información   acerca   de   cómo   debe   tratar   el   resultado   –   de   éxito   o   error   –   de   cada   operación.   Requiere   orden  superior     Se  u2liza  una  arquitectura  dirigida  por  eventos   que  permite  a  las  operaciones  no  bloqueantes   informar   de   su   terminación   mediantes   señales   de   éxito   o   fracaso.   Requiere   correlación   para   sincronizar   I.  Modelo  de  Paso  de  ConQnuaciones   II.  Modelo  de  Eventos       Para  dar  respuesta  al  problema  anterior  –  cómo  dar  tratamiento  de  con2nuidad  al  resultado   de   las   operaciones   no   bloqueantes   una   vez   que   éstas   han   terminado   –   se   han   establecido   diferentes  modelos  de  programación  asíncrona.  Las  bondades  de  dichos  modelos  se  valoran  en   términos   de   cuánto   permiten   aproximar   la   programación   asíncrona   a   un   esquema   lo   más     parecido  al  secuencial.   Se   razona   con   los   valores   de   retorno   de   las   operaciones   no   bloqueantes   de   manera   independiente  del  momento  del  2empo  en  que   dichos  valores  –  de  éxito  o  fallo  –  se  obtengan   Se   u2lizan   generadores   para   devolver   temporalmente  el  control  al  programa  llamante   y  retornar  en  un  momento  posterior  a  la  ru2na   restaurando   el   estado   en   el   punto   que   se   abandonó  su  ejecución   III.  Modelo  de  Promesas   IV.  Modelo  de  Generadores  
  • 8. @javiervelezreye  1-­‐8     Introducción   Programación  Asíncrona  en  Node  JS   IV.  Un  ejemplo     Para  entender  compara2vamente  cada  uno  de  estos  cuatro  modelos  u2lizaremos  a  lo  largo  de   esta   charla   un   sencillo   ejemplo   que   expone   los   3   2pos   de   problemas   caracterís2cos   relacionados  con  el  control  de  flujo  dentro  de  programas  asíncronos.   Dada   una   colección   de   ficheros,   leer   su   contenido  y  contabilizar  el  número  total  de   ocurrencias   de   cada   carácter   contenido   dentro  de  los  mismos     1.  Leer  cada  fichero  en  paralelo   2.  Contabilizar  su  número  de  ocurrencias   3.  Sumar  los  resultados   init   read   count   add   ¿Cómo  paralelizar?   ¿Cómo  secuenciar?   ¿Cómo  sincronizar?   Sequen,al.js  
  • 9. Javier  Vélez  Reyes    @javiervelezreye   Javier.veler.reyes@gmail.com   2  Node  JS  como   Lenguaje  Asíncrono   §  La  Asincronía  de  Node  JS   §  Principios  Arquitectónicos  de  Node  JS   §  Arquitectura  de  Node  JS   Node  JS  como  Lenguaje  Asíncrono     Programación  Asíncrona  en  Node  JS  
  • 10. @javiervelezreye  1-­‐10     Node  JS  como  Lenguaje  Asíncrono   Programación  Asíncrona  en  Node  JS   I.  La  Asincronía  de  Node  JS     Parece  natural  pensar  que  la  programación  asíncrona  exige  de  un  contexto  mul2-­‐hilo  ya  que  el   carácter   no   bloqueante   se   consigue   por   medio   de   una   suerte   de   ejecución   simultanea   que   transcurre  en  un  segundo  plano  del  flujo  principal  del  programa.  Sin  embargo,  esto  no  implica   necesariamente  un  contexto  de  ejecución  concurrente  ya  que  las  operaciones  no  bloqueantes   pueden  ejecutarse  de  forma  aislada.   Node   JS   is   a   pladorm   built   on   Chrome's   JavaScript   run2me   for   easily   building   fast,   scalable   network   applica2ons.   Node   JS   uses   an   event-­‐driven,   non-­‐ blocking   I/O   model   that   makes   it   lightweight   and   efficient,   perfect   for   data-­‐intensive   real-­‐2me   applica2ons  that  run  across  distributed  devices.   Node  JS  es  un  lenguaje  single-­‐thread  pero  que   aplica   mul2-­‐threading   en   los   procesos   de   entrada   salida   y   es   ahí   donde   se   aplica   el   carácter  no  bloqueante   Modelo  no  bloqueante  de  E/S   Node   JS   u2liza   alterna2vamente,   como   veremos,  el  modelo  de  paso  de  con2nuaciones   y  el  de  eventos  si  bien  su  arquitectura  general   está  dirigida  por  un  loop  general  de  eventos   Arquitectura  dirigida  por  eventos  
  • 11. @javiervelezreye  1-­‐11                     Node  JS  como  Lenguaje  Asíncrono   Programación  Asíncrona  en  Node  JS   II.  Principios  Arquitectónicos  de  Node  JS     A   pesar   de   que   recientemente   Node   JS   está   recibiendo,   especialmente   desde   ciertas   comunidades  compe2doras,    fuertes  crí2cas  rela2vas  a  su  aprovechamiento  de  los  ciclos  de   cómputo   por   tratarse   de   un   entorno   single-­‐thread,   su   filosoga   se   basa   en   tres   fuertes   principios  arquitectónicos.     Esta   experimentalmente   comprobado   que   procesamiento  de  las  operaciones  de  E/S  es  el   que   mayor   coste   implica   dentro   de   las   arquitecturas  Hw.   1.  La  E/S  es  lo  que  más  coste  implica   Como   consecuencia   el   esquema   de   comportamiento  de  Node  JS  se  puede  resumir   en   aquellas   partes   del   proceso   de   la   pe2ción   que   merezca   la   pena   paralelizar   (E/S)   se   ejecutarán   de   forma   no   bloqueante   mientras   que   el   resto   ejecuta   en   un   esquema   single-­‐ thread   3.  Todo  en  paralelo  menos  tu  código   Dedicar  un  hilo  para  enhebrar  el  procesamiento   de   cada   solicitud   entrante,   como   hacen   otras   arquitecturas   servidoras   (Apache)   resulta   demasiado  caro  en  memoria   2.  Dedicar  un  hilo  por  solicitud  es  caso  
  • 12. @javiervelezreye  1-­‐12                               Node  JS  como  Lenguaje  Asíncrono   Programación  Asíncrona  en  Node  JS   III.  Arquitectura  de  Node  JS     Node   JS   is   a   pladorm   built   on   Chrome's   JavaScript   run2me   for   easily   building   fast,   scalable   network   applica2ons.  Node  JS  uses  an  event-­‐driven,  non-­‐blocking   I/O  model  that  makes  it  lightweight  and  efficient,  perfect   for  data-­‐intensive  real-­‐2me  applica2ons  that  run  across   distributed  devices.   Llegan   las   solicitudes   a   Node  JS  desde  el  exterior   1.  Nueva  Solicitud   Un  único  hilo  se  encarga  de   gesEonar   las   solicitudes   entrantes   2.  GesQón   Las   operaciones   de   E/S   se   procesan   en   paralelo   en   modo  no  bloqueante   3.  Ejecución  no  bloquante   Todo  Se  Ejecuta  en  Paralelo   menos  tu  Código     Cuando   la   operación   termina  vuelve  al  loop   4.  Finaliza  la  operación   Se   ejecuta   la   lógica   de   conEnuidad   que   procesa   los  resultados   5.  Procesar  resultados  
  • 13. Javier  Vélez  Reyes    @javiervelezreye   Javier.veler.reyes@gmail.com   3  Modelo  de  Paso  de   Con,nuidades   §  Qué  es  una  Con2nuación   §  Control  de  Flujo  Mediante  Con2nuaciones   §  Ejemplo   §  Librerías   §  Conclusiones   Modelo  de  Paso  de  Con,nuidades   Programación  Asíncrona  en  Node  JS  
  • 14. @javiervelezreye  1-­‐14     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  ConQnuación     El  modelo  na2vo  que  u2liza  Node  JS  en  sus  APIs  para  dar  soporte  a  la  programación  asíncrona   es   el   de   paso   de   con2nuaciones.   Cada   operación   no   bloqueante   recibe   una   función   como   úl2mo   parámetro   que   incluye   la   lógica   de   con2nuación   que   debe   ser   invocada   tras   la   finalización  de  la  misma  tanto  para  procesar  los  resultados  en  caso  de  éxito  como  para  tratar   los  fallos  en  caso  de  error.   function div(a, b, callback) { if (b === 0) callback (Error (...)) else { var result = a / b; callback (null, result); } } Proveedor   div (8, 2, function (error, data) { if (error) console.error (error); else console.log (data); }); Cliente   La  función  de  conEnuación  permite  indicar   a   la   operación   bloqueante   como   debe   proceder   después   de   finalizada   la   operación   Paso  de  ConQnuación  
  • 15. @javiervelezreye  1-­‐15     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  ConQnuaciones     La  manera  de  proceder  dentro  de  este  modelo  para  establecer  flujos  de  ejecución  secuenciales   exige  ir  encadenando  cada  función  subsiguiente  como  con2nuación  de  la  anterior  donde  se   procesarán   los   resultados   tanto   en   caso   de   éxito   como   de   fracaso.   Esto   conduce   a   una   diagonalización  del  código  que  se  ha  dado  en  llamar  pirámide  del  infierno  (callback  hell),  por  su   falta  de  manejabilidad  prác2ca  en  cuanto  crece  mínimamente  el  número  de  encadenamientos   secuenciales.   A.  Secuenciamiento   mul(2, 3, function (error, data) { if (error) console.error (error); else div(data, 4, function (error, data) { if (error) console.error (error); else add(data, 5, function (error, data) { ... }); }); }); mul  (2,  3)   div  (3,  4)   add  (4,  5)   2  *  3  /  4  +  5      
  • 16. @javiervelezreye  1-­‐16     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  ConQnuaciones     La  paralelización  –  ejecución  asíncrona  –  de  las  operaciones  no  bloqueantes  es  inmediata  ya   que   su   mera   invocación   ejecuta   en   segundo   plano   por   definición.   Para   conver2r   en   no   bloqueantes  las  operaciones  bloqueantes,  se  requiere  un  pequeño  proceso  de  encapsulación   funcional  que  lance  la  operación  en  segundo  plano.   B.  Paralelización   add(2, 3, function (error, data) {...}); sub(3, 4, function (error, data) {...}); add  (2,  3)   sub(3,  4)   function doAsync (fn, callback, self) { return function () { var allParams = [].slice.call(arguments); var params = allParams.slice (0, allParams.length - 1); var callback = allParams[allParams.length - 1]; setTimeout (function () { var results = fn.apply (self, params) callback (null, results); }, 0); }; }
  • 17. @javiervelezreye  1-­‐17     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  ConQnuaciones     La  sincronización  de  funciones  de  con2nuación  requiere  encadenar  al  final  de  cada  secuencia   paralela  una  función  de  terminación  que  aplique  cierta  lógica  sólo  una  vez  que  se  compruebe   que  todas  los  ramas  paralelas  han  terminado.  Para  implementar  esta  comprobación  se  u2lizan   esquemas  basados  en  contadores.   C.  Sincronización   function doParallel(fns, endCallback, params) { var pending = fns.length; var callback = function (error, data) { <<processing data && error>> pending --; if (pending === 0) { endCallback(); } } for (var index = 0; index <fns.length; index ++) { fns[index].apply (this, params[index], callback); } } doParallel ([add, sub], function (error, data) { console.log (data) }, [[2,3],[4,5]]); add  (2,  3)   sub  (4,  5)   console  
  • 18. @javiervelezreye  1-­‐18     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   III.  Ejemplo     Dada   una   colección   de   ficheros,   leer   su   contenido  y  contabilizar  el  número  total  de   ocurrencias   de   cada   carácter   contenido   dentro  de  los  mismos     1.  Leer  cada  fichero  en  paralelo   2.  Contabilizar  su  número  de  ocurrencias   3.  Sumar  los  resultados   init   read   count   add   Paralelización   Secuenciamiento   Sincronización   Un   bucle   permite   lanzar   en   ejecución   todos   los   pares   no   bloqueantes   de   leer-­‐contar   de   forma  no  bloqueante   Cada  par  leer-­‐contar  se  encadena   a  través  del  paso  de  funciones  de   conEnuación   Para   sincronizar   cada   rama   paralela   recibe   una   úlEma   conEnuación   que   ejecuta   lógica   de   terminación  una  vez  que  se  ha  asegurado  que  todas   las  ramas  han  terminado     Con,nua,ons.js  
  • 19. @javiervelezreye  1-­‐19     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   IV.  Librerías     Existen  numerosas  librerías  que  pueden  ayudarnos  a  hacer  la  vida  más  fácil  cuando  trabajamos   con   un   modelo   de   programación   asíncrona   basado   en   con2nuaciones.   Algunas   de   ellas   no   están   estrictamente   relacionadas   con   la   programación   asíncrona   sino   con   el   paradigma   funcional  lo  cual  se  debe  a  que  los  mecanismos  de  inyección  de  con2nuaciones  son  en  esencia   ar2ficios  funcionales.     Async   Fn.js   Join   Async   es   tal   vez   la   librería   más   conocida   y   ampliamente   uElizada   para   la   programación   asíncrona   basada   en   conEnuaciones.   Ofrece   métodos   de   control   de   flujo   variados   para   funciones  no  bloqueantes   Fn.js  es  una  excelente  librería  que  implementa   disEntos   métodos   de   gesEón   funcional.   Su   aplicabilidad   prácEca   en   este   contexto   está   relacionada   con   las   capacidades   que   expone   para   generar   funciones   no   bloqueantes   y   aplicar  currificación   Join   es   una   implementación   del   método   de   sincronización   que   hemos   comentado   anteriormente   y   resulta   similar   al   que   puede   encontrarse   en   otros   lenguajes   como   C   que   opera   con   threads.   También   puede   usarse   en   promesas   aunque   su   uso   resulta   menos   relevante  
  • 20. @javiervelezreye  1-­‐20     Modelo  de  Paso  de  Con2nuidades   Programación  Asíncrona  en  Node  JS   V.  Conclusiones     La   programación   asíncrona   basada   en   con2nuidades  puede  ser  una  buena  opción  para   situaciones  en  que  la  lógica  de  control  de  flujo   es   muy   sencilla.   Tal   suele   ser   el   caso   de   programas  en  Node  JS  que  permiten  definir  una   respuesta  no  bloqueante  a  pe2ciones  entrantes     No  obstante,  cuando  la  lógica  de  control  resulta   mínimamente   elaborada   el   proceso   de   razonamiento  sobre  el  programa  se  complica  lo   cual  redunda  en  un  código  con  lógica  funcional   distribuida   y   digcil   de   leer,   entender   y   mantener.   Lo  Bueno   Lo  Malo   Sencillo  para  esquemas   solicitud  /  respuesta   Alineado  con  los   esquemas  de   programación  funcional   Fácil  de  entender  como   mecanismo  conceptual     Complejidad  en  la  definición  de   una  lógica  de  control  de  flujo   elaborada   Di`cil  establecer   mecanismos  de   sincronización       La  lógica  de  control   queda  distribuida  entre   cada  rama  no   bloqueante   Di`cil  de  seguir,  leer  y   mantener  a  medida  que   crece  el  código    
  • 21. Javier  Vélez  Reyes    @javiervelezreye   Javier.veler.reyes@gmail.com   4  Modelo  de   Eventos   §  Qué  es  una  Arquitectura  Dirigida  por  Eventos   §  Control  de  Flujo  Mediante  Eventos   §  Ejemplo   §  Librerías   §  Conclusiones   Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS  
  • 22. @javiervelezreye  1-­‐22     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  Arquitectura  dirigida  por  Eventos     Un   evento   es   la   señalización   de   un   acontecimiento   relevante   dentro   del   ecosistema   de   negocio.  Anatómicamente  están  formados,  kpicamente,  por  un  2po,  una  marca  de  2empo  y   un   conjunto   de   datos   que   caracteriza   el   contexto   en   el   que   se   produjo   el   evento.   Las   arquitecturas  de  eventos  (EDA)  proporcionan  un  mecanismo  de  comunicación  entre  clientes  y   proveedores  en  relación  1:N  y  con  desacoplamiento  nominal.  Una  de  sus  muchas  aplicaciones   es  en  los  problemas  de  procesamiento  asíncrono  de  datos.   Proveedor   Cliente   registro   noEficación   reacción   evento   Arquitectura  de  Eventos   Se   produce   una   comunicación   desacoplada   entre   proveedores   y   clientes   a   través   de   un   mecanismo   de   registro/noEficaciones.   Nótese   que   en   este   esquema   las   flechas   no   indican   invocaciones  sino  comunicación  indirecta  
  • 23. @javiervelezreye  1-­‐23     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  Arquitectura  dirigida  por  Eventos     En  las  arquitecturas  centralizadas  dirigidas  por  eventos  existe  un  mediador  central  –  bus  de   comunicaciones   –   que   se   encarga   de   hacer   efec2vo   el   proceso   de   registro   de   los   clientes   escuchadores  y  de  lanzar  las  no2ficaciones  bajo  demanda  de  los  proveedores  a  los  mismos.   Este  mecanismo  permite  una  cardinalidad  N:N.  Este  esquema  se  conoce  bajo  el  nombre  de   patrón  PUB/SUB.   Arquitectura  Centralizada   Proveedor   Cliente   evento   manejador  noEficación   Bus   var bus = Bus.create (); bus.send(‘app.module.event’, data); var bus = Bus.create (); bus.receive(‘app.module.event’, function (data) { ... }); bus.refuse(‘app.module.event’); bus.refuseAll();
  • 24. @javiervelezreye  1-­‐24     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  Arquitectura  dirigida  por  Eventos     En   las   arquitecturas   distribuidas   dirigidas   por   eventos   cada   proveedores   es   responsable   de   ges2onar  la  suscripción  de  sus  clientes  y  de  enviar  las  no2ficaciones  cuando  se  produce  un   evento.   El   mecanismo   de   comunicación   también   es   desacoplado   nominalmente   pero   la   cardinalidad   kpicamente   es   de   1:N   entre   el   proveedor   y   los   clientes.   Este   esquema   se   corresponde  con  el  patrón  observador-­‐observable  o  event  emibers  en  jerga  Node  JS.   Arquitectura  Distribuida   var events = require(‘events’); var emitter = new events.EventEmitter(); emitter.emit(‘app.module.event’, data); emmiter.on(‘app.module.event’, function h(data) { ... }); bus.removeListener(‘app.module.event’, h); bus.removeAllListeners(‘app.module.event’); Proveedor   Cliente   registro   noEficación   Manejadores   registrados  
  • 25. @javiervelezreye  1-­‐25     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Eventos     El   secuenciamiento   dentro   de   este   modelo   se   consigue   a   través   del   encadenamiento   de   escuchadores.   Los   resultados   de   las   operaciones   van   cayendo   en   cascada   desde   la   primera   hasta  la  úl2ma  acumulándose  parcialmente  hasta  llegar  a  un  resultado  final  que  es  recogido  y   procesado  por  el  cliente.   A.  Secuenciamiento   var addEmitter = new events.EventEmitter(); var mulEmitter = new events.EventEmitter(); function add(x, y) { addEmitter.emit(‘result’, x+y); } function mul(z) { addEmitter.on(‘result’, function (data){ mulEmitter.emit(‘result’, data * z); }); } mul(5); mulEmitter.on(‘result’, function (data){ console.log(data); }); add (2,3); r  =  add  (x,  y)   mul  (r,  z)   (2  +  3)  *  5  
  • 26. @javiervelezreye  1-­‐26     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Eventos     En  tanto  que  las  arquitecturas  dirigidas  por  eventos  establecen  un  marcado  desacoplamiento   entre   los   agentes   par2cipantes,   lo   único   que   es   necesario   hacer   para   paralelizar   varias   operaciones  es  hacer  que  cada  una  opere  de  manera  independiente  y  lance  eventos  cuando   genere  resultados.   B.  Paralelización   add  (2,  3)   sub(3,  4)   var addEmitter = new events.EventEmitter(); var subEmitter = new events.EventEmitter(); function add(data) { addEmitter.emit(‘result’, x+y); } function sub(x, y) { subEmitter.emit(‘result’, x-y); } var emitter = new events.EventEmitter(); function add(x, y) { emitter.emit(‘add’, x+y); } function sub(x, y) { emitter.emit(‘sub’, x-y); }
  • 27. @javiervelezreye  1-­‐27     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Eventos     Finalmente,  la  sincronización  requiere  un  proceso  de  escucha  de  todas  las  fuentes  emisoras  de   eventos   que   operan   sobre   el   final   de   cada   rama   paralela.   Debe   incluirse   en   las   funciones   manejadoras   lógica   de   tratamiento   que   emita   nuevos   eventos   más   generales   con   datos   resultantes  el  proceso  de  sincronización.  A  esto  se  le  llama  correlación  de  eventos.     C.  Sincronización   r1=add  (2,  3)   r2=sub  (4,  5)   mul  (r1,r2)   var addEmitter = new events.EventEmitter(); var subEmitter = new events.EventEmitter(); ... function mul() { var r; function h(data) { if (r) {console.log (r * data)} else r = data; }; addEmitter.on (‘result’, h); subEmitter.on (‘result’, h); } mul (); Correlación  de  Eventos   Existe   una   gran   colección   de   patrones   de   diseño   propios   de   las   arquitecturas   de   correlación   entre   los   que   se   cuentan,   transformaciones,   agregados,   filtros   o   abstracciones  temporales  
  • 28. @javiervelezreye  1-­‐28     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   III.  Ejemplo     Dada   una   colección   de   ficheros,   leer   su   contenido  y  contabilizar  el  número  total  de   ocurrencias   de   cada   carácter   contenido   dentro  de  los  mismos     1.  Leer  cada  fichero  en  paralelo   2.  Contabilizar  su  número  de  ocurrencias   3.  Sumar  los  resultados   init   read   count   add   Paralelización   Secuenciamiento   Sincronización   Se  lanzan  a  ejecución  de  forma  iteraEva   todas   las   ramas   secuenciales   para   que   operen  en  paralelo  emiEendo  eventos   La  operación  read  emite  eventos  de  datos  leídos  del   fichero  en  bloques  de  1024  bytes.  La  operación  count   escucha   esos   eventos   y   genera   resultados   acumulaEvamente   que   emite   como   evento   sólo   cuando  read  envía  la  señal  de  fin  de  fichero   La   operación   add   sincroniza   todas   las   operaciones   count.  Va  calculando  los  totales  acumulaEvamente  y   sólo  emite  un  evento  cuando  determina  que  se  han   leído  todos  los  resultados   Events.js  
  • 29. @javiervelezreye  1-­‐29     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   IV.  Librerías     Dado   que   existen   dos   es2los   arquitectónicos   que   operan   dentro   del   modelo   de   las   arquitecturas  dirigidas  por  eventos  –  el  centralizado  y  el  distribuido  –    parece  razonable  dividir   las  contribuciones  de  librerías  que  existen  entre  esas  dos  categorías.   Events   Events   es   un   módulo   estándar   de   Node   JS   uElizado   para   trabajar   con   eventos.   Dispone   de   un   constructor   de   emisor   de   eventos   con   todos   los   métodos   necesarios   para   el   registro,   desregistro  y  propagación  de  eventos.     Arquitecturas  Distribuidas   UQl   Algunos  autores  uElizan  el  método  inherits  de  la   librería   estándar   uEl   con   el   fin   de   explotar   las   capacidades  de  la  librería  events  por  herencia  en   lugar  de  por  delegación   Postal   Postal   es   un   bus   de   comunicaciones   que   implementa  el  patrón  PUB-­‐SUB  tanto  para  cliente   como   para   servidor.   Usa   expresiones   regulares   sobre  el  Epo  de  eventos  para  gesEonar  familias  y   goza  de  buena  comunidad   Arquitecturas  Centralizadas  
  • 30. @javiervelezreye  1-­‐30     Modelo  de  Eventos   Programación  Asíncrona  en  Node  JS   V.  Conclusiones     El   modelo   dirigido   por   eventos   ofrece   grandes   posibilidades  y  da  respuesta  a  un  abanico  nuevo   de   problemas   que   resultan   concomitantes   con   la   programación   reac2va   y   las   soluciones   de   correlación  de  eventos.   Aunque  este  modelo  es  altamente  prometedor   y   supone   grandes   ventajas   con   respecto   al   de   paso   de   con2nuaciones,   no   deja   de   tener   detractores  que  consideran  el  uso  de  promesas   un  artefacto  demasiado  ar2ficial  e  incomodo  de   tratar.   Lo  Bueno   Lo  Malo   Desacoplamiento   nominal   Esquemas  de   comunicación  1:N  o  N:M   Fácil  extensibilidad  del  sistema   reacQvo  por  medio  de  la  adición   de  nuevos  manejadores   Los  procesos  de  coordinación   resultan  complicados   La  lógica  de   secuenciamiento  queda   diluida  entre  los   manejadores   Resulta  más  invasivo   que  otras  soluciones   Código  di`cil  de  seguir,  mantener   y  depurar  a  medida  que  crece  el   tamaño  del  problema       Razonamos  localmente  en   problemas  desacoplados  
  • 31. Javier  Vélez  Reyes    @javiervelezreye   Javier.veler.reyes@gmail.com   5  Modelo  de   Promesas   §  Qué  es  una  Promesa   §  Control  de  Flujo  Mediante  Promesas   §  Ejemplo   §  Librerías   §  Conclusiones   Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS  
  • 32. @javiervelezreye  1-­‐32     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  Promesa     Una  promesa  es  una  abstracción  computacional  que  representa  un  compromiso  por  parte  de   la  operación  no  bloqueante  invocada  de  entregar  una  respuesta  al  programa  llamante  cuando   se  obtenga  un  resultado  tras  su  finalización.  La  promesa  es  un  objeto  que  expone  dos  métodos   inyectores  then  y  fail  para  incluir  la  lógica  de  tratamiento  en  caso  de  éxito  o  fracaso.   var promise = div (a, b); promise.then (function (data) { console.log (data) }).fail (function (error) { console.error (error) }); La   promesa   incluye   dos   funciones,   then   y   fail,   que  permiten  indicar  cómo  tratar  los  resultados   o  manejar  los  errores  una  vez  que  la  operación   no  bloqueante  ha  terminado   Inyección  de  manejadores   function div (x, y) { var result = ... return <<toPromise (result)>>; } Se   recupera   el   control   sobre   el   flujo   del   programa.   Los   proveedores   vuelven   a   devolver   (promesas  de)  valores  y  los  clientes  uElizar  esas   (promesas  de)  valor  en  una  expresión   Comunicación  basada  en  promesas  
  • 33. @javiervelezreye  1-­‐33     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  Promesa     Las  promesas  responden  a  un  sencillo  ciclo  de  vida  que  es  necesario  conocer  para  operar  con   ellas  convenientemente.  El  valor  esencial  de  una  promesa  reside  en  2  principios.  Primero  que   la  lógica  de  tratamiento  en  caso  de  éxito  o  fracaso  sólo  se  ejecuta  una  vez.  Y  segundo  que  se   garan2za  la  ejecución  de  la  lógica  de  éxito  o  fracaso  aunque  la  promesa  se  resuelva  antes  de   haber   inyectado   sus   manejadores.   La   promesa   espera,   si   es   necesario   a   disponer   de   sus   manejadores.   Ciclo  de  vida  de  una  promesa   Se  espera  la  finalización   del  método  async   Pending   Fulfilled   Rejected   Resolved   El  manejador  aún   no  se  ha  ejecutado,   esté  inyectado  o  no   Sebled   El  método  async  ha   terminado  con  una   respuesta   value   error   then  (value)   fail  (error)   Se  ha  ejecutado  la   función  manejadora   de  éxito  o  de  fracaso  
  • 34. @javiervelezreye  1-­‐34     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Una  Promesa     Existen   diversas   formas   de   obtener   promesas   que   pueden   iden2ficarse   como   patrones   de   construcción   que   aparecen   recurrentemente   al   u2lizar   este   modelo.   A   con2nuación   comentamos  los  más  relevantes  con  ejemplos  en  la  librería  Q.   Construcción  de  Promesas   var promise = getPromise (); Obtención  directa   return Q.fcall (function () { return value; }); Invocación  funcional   var promise = Q.resolve (value); Resolución  directa   var promise = Q.reject(error); Rechazo  directo   var deferred = Q.defer(); if (error) deferred.reject (error); if (data) deferred.resolve (data); return deferred.promise; Factoría  de  diferidos   var f = Q.denodeify(fs.readFile); var f = Q.nfbind (fs.readFile); Q.nfcall (fs.readFile (...)); Denodificación  
  • 35. @javiervelezreye  1-­‐35     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Promesas     La  lógica  de  control  secuencial  puede  obtenerse  mediante  el  encadenamiento  the  sucesivas   invocaciones  al  método  de  inyección  then.  Este  encadenamiento  provoca  un  comportamiento   secuencial  puesto  que  cada  función  then  genera,  al  retornar,  una  promesa  que  encapsula  el   valor  devuelto  (a  menos  que  éste  sea  ya  una  promesa)  lo  que  obliga  a  mantener  el  orden.   A.  Secuenciamiento   Q.resolve (2) .then (function (value) { return value - 1; }) .then (function (value) { return value - 1; }) .then (function (value) { if (value===0) throw Error (); return (8 / value); }) .then (function (value) { return value + 1; }) .fail (function (error) { console.log (error); }); 2 1 0 error  
  • 36. @javiervelezreye  1-­‐36     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Promesas     Al  igual  que  ocurría  en  el  modelo  de  paso  de  con2nuidades,  la  paralelización  se  consigue  por   invocación  directa  de  las  operaciones,  ya  que  éstas  2enen  un  comportamiento  no  bloqueante.   En   este   modelo   sin   embargo   la   programación   resulta   más   natural   ya   que   cada   operación   devuelve  un  valor  de  retorno  instantáneamente  en  forma  de  promesa.   B.  Paralelización   var r1 = add(2, 3); var r2 = sub(3, 4); add  (2,  3)   sub(3,  4)   function doParallel(fns, params) { var promises = []; for (var index = 0; index < fns.length; index ++) { var p = Q.fapply (fns[index], params[index]); promises.push (p); } return promises; } var promises = doParallel ([add, sub], [[2,3],[4,5]]); var r1 = Q.fcall (add, 2, 3); var r2 = Q.fcall (sub, 3, 4);
  • 37. @javiervelezreye  1-­‐37     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Promesas     Dado  que  disponemos  de  los  resultados  potenciales  en  forma  de  promesas  es  fácil  ar2cular   sobre  ellos  polí2cas  de  sincronización.  El  método  all  genera  una  promesa  que  toma  una  array   de  promesas  y  se  resuelve  a  un  array  de  valores  cuando  todas  las  promesas  se  han  resuelto.  Si   hay   fallo   se   devuelve   el   de   la   primera   promesa   del   array   en   fallo.   allSebled   por   su   parte   resuelve  cuando  todas  las  promesas  estan  en  senled.  Finalmente,  spread  es  la  versión  en  array   del  método  then.   C.  Sincronización   var promises = doParallel ([add, sub], [[2,3],[4,5]]); Q.all (promises).then (function (values) { console.log (values); }); add  (2,  3)   sub  (4,  5)   var promises = doParallel ([mul, div], [[2,3],[4,0]]); Q.allSettled (promises).spread (function (vMul, vDiv) { if (vMul.state === "fulfilled") console.log (vMul.value); if (vDiv.state === "fulfilled") console.log (vDiv.value); }); console  
  • 38. @javiervelezreye  1-­‐38     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   III.  Ejemplo     Dada   una   colección   de   ficheros,   leer   su   contenido  y  contabilizar  el  número  total  de   ocurrencias   de   cada   carácter   contenido   dentro  de  los  mismos     1.  Leer  cada  fichero  en  paralelo   2.  Contabilizar  su  número  de  ocurrencias   3.  Sumar  los  resultados   init   read   count   add   Paralelización   Secuenciamiento   Sincronización   Se  lanzan  a  ejecución  de  forma  iteraEva   todas  las  ramas  paralelas  y  se  construye   un  array  de  promesas  para  su  posterior   sincronización.     El  secuenciamiento  consiste  meramente   en  encadenar  las  funciones  de  lectura  y   conteo  con  dos  métodos  then.   Se  recogen  las  promesas  que  resultan  de  cada  rama   secuencial   en   un   array   para   poderlas   sincronizar   haciendo  uso  del  método  all.   Promises.js  
  • 39. @javiervelezreye  1-­‐39     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   IV.  Librerías     Existen  varias  librerías  que  implementan  el   modelo   de   promesas.   Tal   vez   la   de   mayor   comunidad  es  Q,  aunque  otras  como  When   o   RSVP,   también   gozan   de   bastante   tracción.   En   aras   a   disponer   de   un   marco   compara2vo  de  referencia  se  ha  definido  el   estándar  Promises  A+  que  rige  todas  todas   las  librerías  con  objetos  then-­‐able.  
  • 40. @javiervelezreye  1-­‐40     Modelo  de  Promesas   Programación  Asíncrona  en  Node  JS   V.  Conclusiones     Hemos  recuperado  en  gran  parte  el  control  de   flujo  del  programa  de  manera  que  el  esquema   de   desarrollo   de   aplicaciones   asíncronas   basadas   en   promesas   se   parece   algo   más   al   es2lo   secuencial     manteniendo   su   carácter   no   bloqueante.   Aunque  este  modelo  es  altamente  prometedor   y   supone   grandes   ventajas   con   respecto   al   de   paso   de   con2nuaciones,   no   deja   de   tener   detractores  que  consideran  el  uso  de  promesas   un  artefacto  demasiado  ar2ficial  e  incomodo  de   tratar.   Lo  Bueno   Lo  Malo   Recuperamos  el  return  y   la  asignación   APIs  más  limpias  sin   métodos  de  callback   (callback  en  cliente)   Estructura  del  programa   más  similar  a  la   programación  secuencial     No  deja  de  ser  necesario   inyectar  funciones  manejadoras   de  éxito  y  error   Resulta  di`cil  depurar   hasta  que  las  promesas   no  se  han  resuelto     Resulta  más  invasivo   generar  APIs  que   consuman  y  generen   promesas  Es  imprescindible  hacer   uso  de  librerías  de   terceros  para  gesQonar   las  promesas   Razonamos  con  promesas   como  valores  de  futuro  
  • 41. Javier  Vélez  Reyes    @javiervelezreye   Javier.veler.reyes@gmail.com   6  Modelo  de   Generadores   §  Qué  es  un  Generador   §  Los  Generadores  como  Modelo  de  Asincronía   §  Control  de  Flujo  Mediante  Generadores   §  Ejemplo   §  Librerías   §  Conclusiones   Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS  
  • 42. @javiervelezreye  1-­‐42     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   I.  Qué  es  Un  Generador     Imagina  un  procedimiento  que  pudiera  ser  interrumpido  en  su  ejecución  en  cualquier  punto   antes  de  su  terminación  para  devolver  el  control  al  programa  llamante  y  más  adelante  éste   volver  a  cederle  el  control  para  que  con2núe  justo  en  el  punto  donde  fue  interrumpido  y  con  el   estado  que  tenía.  Eso  es  un  generador.  Antes  de  ver  su  aplicación  en  modelos  de  asincronía   veamos  cómo  funciona  y  cuál  puede  ser  su  aplicabilidad  prác2ca.     function* fibonacci () { var a = 1; var b = 0; var aux; while (true){ aux = a + b; a = b; b = aux; var reset = yield b; if (reset){ a = 1; b = 0; } } } var fib = fibonacci() { for (var i=0; i<10; i++) { var f = fib.next(); console.log(f.value); } } console.log (fib.next().value); console.log (fib.next().value); console.log (fib.next(true).value); console.log (fib.next().value); console.log (fib.next().value); Yield   Suspende   la   ejecución   y  devuelve  b   Reset   ObEene   como   retorno   el  argumento  de  next   Next   Inicia  o  reanuda  la  ejecución   hasta  el  siguiente  next   {  value:  n,      done:  false  }   Generators.fib.js   Requiere   §  NodeJS  >  0.11     §  flag  -­‐-­‐harmony  
  • 43. @javiervelezreye  1-­‐43     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   II.  Los  Generadores  como  Modelo  de  Asincronía   JS  es  un  lenguaje  de  orden  superior  lo  que  implica  que  trata  a  las  funciones  como  cualquier   otro  2po  de  dato.  Pueden  asignarse  a  variables,  pasarse  como  parámetros  o  devolverse  como   resultado.  Lo  bueno  de  esto  úl2mo  es  que  una  función  que  es  devuelta  como  resultado  de   invocar  a  otra  función  man2ene  el  contexto  de  variables  definido  dentro  de  esta  úl2ma  para  su   ejecución.  Veamos  un  ejemplo:   ¿Qué  es  Una  Clausura?   function Logger(cls) { var pre = ‘Logger’; var post = ‘...’; return function (message) { console.log ('%s[%s] - [%s]%s', pre, cls, message, post); } } var log = Logger (‘Generators’); log(‘starting’); log(1234); log(‘end’); function (message) {...} pre post cls clausura   Clausura   Al   devolver   una   función   hacia   fuera   del   ámbito  de  definición  se  manEene  el  contexto   de  variables  y  parámetros  que  dicha  función   Eene   dentro,   de   forma   trasparente.   A   ese   contexto  se  le  llama  clausura  
  • 44. @javiervelezreye  1-­‐44     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   II.  Los  Generadores  como  Modelo  de  Asincronía   En  muchas  ocasiones  resulta  conveniente  conver2r  una  función  de  n  parámetros  en  otra  que   resuelve  el  primer  parámetro  y  devuelve  como  resultado  otra  función  con  n-­‐1  parámetros.    A   esto  se  le  llama  evaluación  parcial  de  una  función.  Cuando  la  evaluación  parcial  se  repite  para   cada  parámetro  de  la  función  el  proceso  se  llama  currificación.   function add(a, b) { return a + b; } ¿Qué  es  Evaluación  Parcial  de  una  Función?   function add(a) { return function (b) { return a + b; } } var r = add(3, 2); var r1 = add(3)(2); var inc = add(1); var r2 = inc(5); Evaluación  total   En   la   evaluación   total   el   cliente   debe   esperar   hasta   obtener   todos   los   parámetros   actuales   (3   y   2)   para  poder  invocar  a  la  función   Evaluación  parcial   En   la   evaluación   parcial   cada   parámetro   (por   orden)   puede  ser  resuelto  de  manera  independiente  en  sucesivas   evaluaciones.  Esto,  como  veremos,  nos  da  la  oportunidad   de  conseguir  que  sean  disEntos  clientes  los  que  realicen   cada  evaluación  parcial  
  • 45. @javiervelezreye  1-­‐45     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   II.  Los  Generadores  como  Modelo  de  Asincronía   En  términos  generales  un  Thunk  es  una  abstracción  computacional  que  sirve  de  vehículo  para   comunicar  información  entre  dos  frameworks  diferentes.  En  nuestro  caso  queremos  pasar  de   un  modelo  de  invocación  basado  en  con2nuaciones  en  otro  que  las  oculte.  Haciendo  uso  de  los   dos  conceptos  anteriores  –  clausuras  y  evaluación  parcial  –  proponemos  construir  el  siguiente   thunk.     function add(a, b, callback){ callback (null, x + y); } ¿Qué  es  un  Thunk?   function add(a, b) { return function (callback) { callback (null, x + y); } } add(3, 2, function(error, data){ console.log (data); }); var r = add(3, 2); r(function (error, data) { console.log (data); }); Thunk   Nuestros   thunks   devuelven   funciones   que   esperan   manejadores   como   parámetros.   De   esta   manera   ocultamos  el  manejador  en  la  primera  evaluación  parcial:   add  (2,3);    
  • 46. @javiervelezreye  1-­‐46     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   II.  Los  Generadores  como  Modelo  de  Asincronía   Podemos  construir  un  framework  sobre  el  que  escribir  generadores  que  devuelvan  thunks  (con   yield)  lo  que  simplifica  el  código  cliente.  El  framework  por  su  parte  va  secuenciando  el  código   del   generador   (con   next)   y   se   interpone   para   resolver   de   forma   transparente   la   segunda   evaluación  parcial  que  corresponde  con  la  función  de  callback.  Su  labor  consiste  en  extraer  los   datos  del  callback  y  retornarlos  al  generador  para  que  éste  los  obtenga  como  una  variable  local   co (function* (){ var r1 = yield add (2,3); var r2 = yield sub (3,4); console.log (r1, r2); })(); Generadores  y  Thunks   Cliente   var co = function (codeGn) { var code = codeGn (); function step(thunk) { if (thunk.done) return thunk.value; else { thunk.value (function (error, data){ step(code.next (data)); }); } } return function () { step(code.next ()); }; }; Framework   Generators.co.js   Requiere   §  NodeJS  >  0.11     §  flag  -­‐-­‐harmony  
  • 47. @javiervelezreye  1-­‐47     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Generadores     De   lo   que   hemos   visto,   el   uso   de   yield   dentro   de   un   generador   evaluado   por   nuestro   framework   asíncrono   permite   a   éste   interponerse   para   capturar   la   función   de   callback   y   resolver   un   thunk   en   su   valor   equivalente.   De   ello   se   deduce   que   cada   vez   que   queramos   secuenciar  operaciones  sólo  tenemos  que  interponer  yield  antes  de  la  operación.   A.  Secuenciamiento   co(function* (){ var r1 = yield mul(2,3); var r2 = yield div(3,4); var r3 = yield add(4,5); console.log (r1, r2, r3); })(); mul  (2,  3)   div  (3,  4)   add  (4,  5)   2  *  3  /  4  +  5       Yield  en  secuencia   Cada   yield   puede   leerse   como   un   paso   dentro   de   una   secuencia  de  operaciones.  Cada  operación  no  bloqueante   (mul,  div  y  add)  devuelve  un  thunk  que  el  framework,  co,   recoge  para  resolver  a  un  valor  y  devolverlo  al  contexto   del  generador  como  una  variable  local  (r1,  r2  y  r3)    
  • 48. @javiervelezreye  1-­‐48     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   II.  Control  de  Flujo  Mediante  Generadores     Razonablemente  todas  aquellas  operaciones  no  bloqueantes  que  no  sean  intercedidas  por  el   framework  a  través  de  la  cláusula  yield  darán  lugar  a  esquemas  de  ejecución  paralelos.  Es  una   prác2ca   común   agrupar   estas   invocaciones   en   colecciones   (arrays   u   objetos)   para   posteriormente  hacer  la  resolución  de  thunks  a  valores.   B.  Paralelización  &  C.  Sincronización   co(function* (){ var r1 = add(2,3); var r2 = sub(3,4); var r = yield [r1, r2]; console.log (r); })(); Array  de  thunks   Cada   operación   no   bloqueante   aquí   es   evaluada   sin   la   clausula  yield  con  lo  que  lo  que  se  obEene  en  r1  y  r2  son   dos  thunks  ejecutados  en  paralelo   add  (2,  3)   sub(3,  4)   Yield  de  Array   Yield   aplicado   a   un   array   se   evalúa   como   el   array  de  los  yields.  Yield  aplicado  a  un  objeto  se   evalúa  como  el  yield  aplicado  a  cada  propiedad   del  objeto.  De  esta  forma,  este  yield  convierte  el   array  de  thunks  en  un  array  de  valores  
  • 49. @javiervelezreye  1-­‐49     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   III.  Ejemplo     Dada   una   colección   de   ficheros,   leer   su   contenido  y  contabilizar  el  número  total  de   ocurrencias   de   cada   carácter   contenido   dentro  de  los  mismos     1.  Leer  cada  fichero  en  paralelo   2.  Contabilizar  su  número  de  ocurrencias   3.  Sumar  los  resultados   init   read   count   add   Paralelización   Secuenciamiento   Sincronización   Mediante   un   bucle,   se   construye   un   array   de   generadores   para   cada   rama   paralela   Se   construye   un   generador   capaz   de   secuenciar  las  dos  operaciones  –  read  y   count   –   que   conforman   cada   rama   paralela   Se  hace  un  yield  de  los  resultados  para  sincronizar  y   se   invoca   a   add   para   obtener   los   totales,   que   se   devuelven   al   cliente   con   otro   yield   ya   que   add   también  es  no  bloqueante   Generators.js   Requiere   §  NodeJS  >  0.11     §  flag  -­‐-­‐harmony  
  • 50. @javiervelezreye  1-­‐50     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   IV.  Librerías     Aunque   existen   varias   librerías   que   dan   soporte   a   esta   idea   –   ar2cular   un   framework   de   soporte   a   la   programación   asíncrona   basado   en   generadores   –   la   que   goza   de   mayor   comunidad   es   co.   En   torno   a   ella   se   pueden   encontrar   una   amplia   colección   de   librerías   u2litarias  vinculadas  que  conforman  el  ecosistema  de  co.   Co   Ecosistema  Co*   Thunkify   El  framework  de  programación  asíncrona  basado   en   generadores   con   mayor   aceptación.   Co   no   sólo   es   capaz   de   operar   con   Thunks   como   abstracción  vehicular  sino  que  también  funciona   con   promesas,   funciones,   generadores   y   funciones  generadoras.   Librerías   específicas,   adaptadores   de   APIs,   servidores,   funciones   uElitarias   de   control   de   flujo…   Todo   un   ecosistema   de   herramientas   para   programar   dentro   del   framework   co.   Se   puede  ver  una  relación  exhausEva  en  la  wiki  de   Co  accesible  desde  github       Se  trata  de  una  simple  función  que  convierte   a   un   thunk   cualquier   función   definida   de   acuerdo  al  modelo  de  paso  de  conEnuidades   estandarizado  por  Node  JS.  
  • 51. @javiervelezreye  1-­‐51     Modelo  de  Generadores   Programación  Asíncrona  en  Node  JS   V.  Conclusiones     La   programación   asíncrona   basada   en   generadores  es,  tal  vez,  la  opción  que  mejor  ha   conseguido  acercar  la  experiencia  de  desarrollo   a  la  programación  secuencial.  A  la  fecha  de  esta   charla   aún   es   pronto   para   saber   si   será   ampliamente  aceptada  por  la  comunidad  o  no.   El   modelo   de   programación   asíncrona   basada   en   generadores   sigue   teniendo   inconvenientes   serios   relacionados   con   la   invasividad   del   framework   y   el   uso   permanente   de   clausulas   yield  para  ar2cular  el  manejo  del  control  flujo.     Lo  Bueno   Lo  Malo   Esquema  de   programación  similar  al   secuencial   Transparencia  en  los   procesos  de  gesQón  de   conQnuaciones   Curva  de  aprendizaje  corta.  Con   pocas  reglas  de  pulgar  se  puede   razonar  fácilmente  en  el   modelo     Todo  código  esta   siempre  dentro  de  un   contexto  Co   El  código  está   plagado  de  yields   ¿qué  está  haciendo  Co   por  debajo?   ArQficialidad  del  código.   Perversión  del  uso  de   los  yields  
  • 52. @javiervelezreye  1-­‐52     Preguntas   Programación  Asíncrona  en  Node  JS   Generadores   Promesas  Eventos   ConQnuaciones   Javier  Vélez  Reyes    @javiervelezreye   Javier.velez.reyes@gmail.com  
  • 53. Javier  Vélez  Reyes    @javiervelezreye   Javier.velez.reyes@gmail.com   Modelo  de  Paso  de  Con,nuaciones,  Eventos,   Promesas  y  Generadores     Programación  Asíncrona  en   Node  JS     Mayo  2014