¿Qué es asincronismo?

Uno de los conceptos con mayor relevancia en JavaScript, y en casi todos los lenguajes de programación, es el asincronismo. Sería raro pensar que, en el desarrollo de aplicaciones web en el 2020, sigamos desarrollando aplicaciones sin asincronismo.

Pero ¿qué es asincronismo? Estas son tareas que al ser ejecutadas pueden ser completadas en el momento o en el futuro y que su comportamiento es no bloqueante.

Un ejemplo común sería el siguiente: si nuestra app solicita el catálogo de productos, esta envía una orden a través de una API, pero es el servidor quién procesa dicha solicitud y en el momento que esté listo devolverá el listado de datos. En este punto nuestra app desconoce el tiempo que se toma el servidor en responder la petición, por lo que si utilizáramos una función síncrona se estaría todo ese tiempo esperando los datos y bloqueando el proceso de las funciones subsecuentes. En cambio una función asíncrona enviará la petición a la API, nuestra aplicación continuará con la ejecución de otras tareas y cuando el servidor responda se notificará que los datos están listos para ser procesados.

Para entender este concepto primero tenemos que tener claro que JavaScript no es capaz de ejecutar más de una tarea a la vez, sin importar la cantidad nucleos que tenga tu computadora o servidor. A pesar de que JavaScript no es un lenguaje multi-tarea, o con paralelismo, es altamente concurrente.

A pesar de lo que se suele creer, la respuesta es que no es necesario contar con más de un núcleo para poder emplear tareas de forma asíncrona. Por ejemplo, una técnica bastante usada es el entrelazado en el que dos tareas grandes se dividen en varias pequeñas y se ejecutan una del primer proceso seguida de otra del siguiente proceso.

Por lo que técnicamente definiremos a JavaScript como un lenguaje de programación con un modelo de concurrencia asíncrono por medio del Event Loop en un único hilo o thread de ejecución. A pesar de que JavaScript no es multitareas este puede delegar la ejecución de ciertas funciones a otros procesos y cuya llamada será devuelta inmediatamente evitando así el bloqueo de la aplicación, cuando dicho proceso haya sido capaz de resolver la tarea enviará un mensaje de notificación y procesará la respuesta mediante el callback, promise o evento.

Para hacer uso del Event Loop deberemos utilizar y comprender dos elementos más: call stack y callback queue. La pila de llamadas o call stack es donde se apilan las llamadas a funciones según el orden en el que llegan, ejecutándose primero las que se encuentran encima; por ejemplo: si una función hace un llamado a otra función, esta última estará en la parte superior y será la que se ejecute primero. Anteriormente habíamos hablado que podíamos delegar tareas a otros procesos que no bloquearan la aplicación y cuyos resultados nos fueran notificados mediante mensajes para procesar las respuestas con callback’s, pues dichos callback’s serán las funciones que se encolan en el callback queue y en el momento que se hayan procesado todas las funciones de la pila de llamadas será el momento en el que las funciones que están en el callback que envíen al call stack para ser ejecutadas.

Existen 3 maneras con las que podemos implementar asincronismo, estas son: Utilizando callback’s, promises y con async/await.

Callback’s

Esta es la forma más antigua para emplear asincronismo en JavaScript. Y consiste en una función que se pasará como parámetro de otra función, en donde la función principal será la encargada de hacer el llamado de nuestro callback (la función parámetro). Cuando esta función principal es no-bloqueante, utilizará este callback para dar respuesta hasta el momento en que los resultados estén listos, hayan sido satisfactorios o no.

Por ejemplo, si queremos consultar datos en Internet lo normal sería que consumamos una API, el resultado estará listo en un tiempo indeterminado por lo que sería lógico emplear asincronismo en este caso, nuestra función no bloqueará el hilo principal de nuestra aplicación y cuando tengamos la respuesta de la API llamaremos al callback para procesar el resultado; ya sea que obtuvimos los datos o un error.

Promises o Promesas

Las promesas son una característica más reciente que fue añadida en la versión 6 del estándar ECMAScript. Esta característica nos permite emplear asincronismo en nuestras aplicaciones y mejora a los callback’s porque evita el callback hell; además de que nos permite escribir un código más limpio. Una promesa se define como una función no-bloqueante y asíncrona cuyo valor de retorno puede estar disponible justo en el momento, en el futuro o nunca.

Async / Await

Esta es la forma más reciente de emplear asincronismo en JavaScript, la cual apareció en la versión 8 del estándar ECMAScript. La técnica introdujo dos palabras reservadas al lenguaje, estas son async y await, las cuales emplearemos en conjunto. Con async podemos definir que una función sea asíncrona. En el caso de await se emplea para esperar un resultado de otra función asíncrona que retorne un objeto promise (las funciones definidas con async también retornan un objeto promise, por lo que pueden ser tratadas como promesas). Cabe destacar que, en una función definida con async, podemos emplear await la cantidad de veces que deseemos por lo que el encadenamiento no es un problema en esta parte.

Por último, para el tratamiento de errores normalmente emplearemos el try/catch bastante común en tantos lenguajes de programación.

Última actualización