Objetivos

Cuando finalices la unidad comprenderás la manera que tiene javascript de tratar la ejecución de código de forma concurrente mediante el bucle de eventos. Entenderás la diferencia entre código bloqueante y no bloqueante y cuando debemos usar uno u otro. También aprenderás a trabajar con funciones asíncronas y callbacks asociados así como con promesas, una forma de tratar el mismo problema que mejora la legibilidad y estructura del código.

Videos de la unidad

A lo largo de la unidad se irán presentando diferentes videos. Aquí te ofrecemos la lista de reproducción con todos los videos de la unidad, para que los tengas más a mano.

Introducción

Javascript es un lenguaje que utiliza la programación asíncrona dirigida por eventos para el tratamiento de la concurrencia, es decir para realizar más de una tarea simultaneamente. Es común escuchar que javascript se ejecuta en un sólo hilo, pero esto es una verdad a medias. Es cierto que hay un hilo principal en el que se ejecuta todo el código que escribimos en nuestros programas. Pero por otra parte existen funciones asíncronas expuestas por la Web API en el navegador o por el propio sistema operativo en el caso de node.js que realizan operaciones de entrada y salida que no bloquean el hilo principal sencillamente por que no se realizan en dicho hilo.Por otro lado hay timers y registros de eventos cuyo mecanismo es externo al hilo principal. Incluso existen los llamados webworkers cuyo código se ejecuta en otro hilo distinto. Cuando finaliza la ejecución del código de estos, emiten un evento para notificar al hilo principal, igual que ocurre con cualquier otro evento como puede ser un clic en un botón.

Probablemente lo más importante de todo esto es conocer que todos los elementos asíncronos de javascript son coordinados por un mecanismo denominado el bucle de eventos. Un mecanismo que se encuentra en el corazón mismo de cualquier entorno de ejecución javascript y del que ya hemos hablado en la segunda unidad.

A lo largo de la unidad presentamos en primer lugar el problema que presenta el código síncrono bloqueante, para pasar a explicar como se resuelve en javascript mediante la programación asíncrona dirigida por eventos. Para ello introducimos un nuevo modelo del bucle de eventos que es  complementario al que dimos en la unidad 2. Posteriormente vemos, mediante un ejemplo concreto cómo introducimos el código asíncrono cuando la aplicación lo requiere y como de manera inevitable este código resulta más farragosos y difícil de seguir. Finalmente introducimos las promesas, unos objetos mediante los que mejoramos la legibilidad y el tratamiento de errores cuando usamos código asíncrono.

El problema: el bloqueo del hilo principal

En este primer video de la unidad explicamos que es el código síncrono bloqueante y el concepto de pila de llamadas del hilo principal. Veremos que existen casos en los que programar exclusivamente con código síncrono provoca una degradación muy notable en la reactividad de la aplicación, debido a que este código se ejecuta en el hilo principal y puede llegar a bloquearlo significativamente cuando las operaciones que realiza tardan demasiado en finalizar. En este primer vídeo planteamos el problema que resolverá la programación asíncrona dirigida por eventos.

 

La solución: programación asíncrona dirigida por eventos

En este vídeo revelamos como podemos hacer para no bloquear el hilo principal de ejecución cuando hacemos operaciones lentas (especialmente si son de entrada/salida). Se trata de utilizar un modelo de programación concurrente, es decir, de porgramación que permite hacer varias cosas a la vez, y que se denomina programación asíncrona dirigida por eventos. La clave de este tipo de programación se encuentra en un mecanismo denominado bucle de eventos, el cual es explicado de manera rigurosa en este video.

Es muy importante que entiendas como funciona el bucle de evento. Por eso hemos utilizado un modelo gráfico que deberías utilizar como modelo mental cuando utilices la programación asíncrona dirigida por eventos en tus aplicaciones.

Programación asíncrona con callbacks

En este vídeo comenzamos mostramos un ejemplo de código síncrono que degrada a la aplicación, en este caso a la interfaz de usuario, debido a la ejecución de funciones lentas en el hilo principal, y continuaremos modificándolo para evitar este problema. La modificación consistirá, como ya te habrás imaginado, en convertir la parte de ejecución lenta en asíncrona.

Después de visualizar el vídeo te querará claro qué es un callback y la importante función que ejercen en este modelo de programación concurrente. También tomarás conciencia de la complicación inevitable, tanto en el código que escribimos como en su seguimiento, que provoca este tipo de programación. Es el precio que debemos pagar si queremos programar una aplicación que reaccione correctamente en todas las situaciones.

Esta complicación se resume en una expresión muy conocida en el mundo javascript: «la maldición de los callbacks«. Algo que ha provocado la búsqueda de nuevas formas de tratar con las funciones asíncronas y sus callbacks asociados. Las promesas, introducidas en el estándar ES6 de javascript, representan una de estas nuevas maneras de trabajar con la programación asíncrona dirigida por eventos.

Programación asíncrona con promesas

Las promesas son objetos que envuelven a código javascript y representan un valor disponible en el futuro. El concepto de promesa es más difícil de definir que de comprender cuando se ven cómo funcionan en la práctica. Por eso en este vídeo nos hemos centrado en visualizar dicho comportamiento con un ejemplo práctico. A lo largo del ejemplo vamos introduciendo paulatinamente varios comportamientos básicos de las promesas que resumimos en 4 observaciones. Si consigues asimilar estas observaciones no te quepa duda de que acabarás dominando la programación asíncrona dirigida por eventos con promesas.

Qué hemos aprendido

  • El bucle de eventos es una parte fundamental del entorno de ejecución de javascript que ofrece la posibilidad de programación asíncrona dirigida por eventos. Esta se basa en
    • la ejecución de funciones asíncrona que no bloquean el hilo principal de ejecución (pues se ejecutan en otro hilo) y
    • el procesamiento de los valores devueltos por dichas funciones asíncronas a través de sus callbacks asociados.
  • Los callbacks son funciones que se pasan como argumentos a las funciones asíncronas. Cuando estas últimas se han resuelto, el bucle de eventos coloca en la pila de llamadas del hilo principal a dicha función de callback, siendo su argumento el valor devuelto por la función asíncrona.
  • Cuando las funciones asíncronas necesitan los valores devueltos por otras funciones asíncronas, necesitamos que los callbacks inicien nuevas llamadas asíncronas, dando lugar este hecho a una organización del código anidada y con aspecto indentado triangular que resulta en un código poco legible.
  • Las promesas son un patrón de programación asíncrona que mejoran la legibilidad y organización del código, así como el tratmiento de los errores.