Sincronismo y Asincronismo en JavaScript
En JavaScript, los conceptos de sincronismo y asincronismo son fundamentales para entender cómo se ejecuta el código y cómo maneja tareas que pueden llevar tiempo, como solicitudes a un servidor o temporizadores.
1. Qué es el Sincronismo? #
- Sincronismo significa que las tareas se ejecutan una después de la otra.
- JavaScript ejecuta el código línea por línea, y no pasa a la siguiente tarea hasta que la actual haya terminado.
- Es como una cola en la que cada persona (tarea) espera su turno hasta que la persona anterior haya terminado.
Ejemplo de código síncrono:
1console.log("Inicio"); 2let resultado = 1 + 2; 3console.log("El resultado es:", resultado); 4console.log("Fin");Salida de consola Inicio El resultado es: 3 Fin
- En este ejemplo, JavaScript imprimirá "Inicio", luego calculará
1 + 2y mostrará el resultado, y finalmente imprimirá "Fin". Todo sucede en orden.
¿Qué es el Asincronismo? #
- Asincronismo significa que algunas tareas pueden comenzar pero no se espera a que terminen para continuar con el siguiente código.
- En JavaScript, esto es útil para realizar tareas que pueden tomar tiempo, como leer un archivo, hacer una solicitud a un servidor, o esperar un tiempo antes de ejecutar algo (temporizadores).
- Es como si alguien en la fila dijera: "Voy a hacer otra cosa mientras espero, continúen sin mí".
Ejemplo de código asíncrono:
1console.log("Inicio"); 2 3setTimeout(() => { 4 console.log("Esto se ejecuta después de 2 segundos"); 5}, 2000); 6 7console.log("Fin");Salida de consola Inicio Fin Esto se ejecuta después de 2 segundos
- En este ejemplo, JavaScript imprime "Inicio", luego configura un temporizador para ejecutar algo después de 2 segundos, y mientras espera, imprime "Fin". Cuando el temporizador termina, imprime el mensaje del
setTimeout.
¿Por qué es importante? #
- Código síncrono es simple y fácil de entender, pero puede bloquear la ejecución si una tarea toma mucho tiempo.
- Código asíncrono es mas dificil de entender y manejar, permite que JavaScript siga ejecutando otras tareas mientras espera que las más lentas terminen, lo que hace que las aplicaciones sean más rápidas y responden mejor.
Ejemplos comunes de asincronismo #
- Solicitudes a un servidor (AJAX/fetch):
- Cuando pides datos a un servidor, puede tardar un poco en responder, pero mientras tanto, tu aplicación puede seguir funcionando.
- Ejemplo:
1fetch('https://randomuser.me/api/') 2 .then(response => response.json()) 3 .then(data => console.log(data.results[0].name.first)); 4console.log("Solicitud enviada...");- Aquí, JavaScript envía la solicitud y sigue adelante. Cuando llegan los datos, se procesan sin haber bloqueado la ejecución.
WARNING
No te preocupes si no entiendes el código ahora, los veremos proximamente con más detalle.
- Promesas y
async/await:- Las promesas son una forma de manejar el asincronismo en JavaScript, indicando que una tarea se completará en el futuro.
- Con
async/await, puedes escribir código asíncrono que parece síncrono, lo que lo hace más fácil de leer. - Ejemplo:
1async function obtenerDatos() { 2 let response = await fetch('https://randomuser.me/api/'); 3 let data = await response.json(); 4 console.log(data.results[0].name.first); 5} 6console.log("Antes de obtener los datos"); 7obtenerDatos(); 8console.log("Después de solicitar los datos");- Aquí, el código espera a que
fetchyresponse.json()se completen, pero la ejecución de otras líneas de código puede continuar mientras espera.
- Aquí, el código espera a que
Laboratorio: intercalar tareas puede perder una actualización #
Si una tarea lee un valor, espera con await y luego escribe una copia modificada,
otra tarea puede cambiar el valor durante esa espera. No hace falta ejecutar dos
hilos para provocar esta condición de carrera. Decide el orden de las operaciones
y compara el resultado con una sección crítica protegida.
Laboratorio interactivo
Condiciones de carrera con await
Dos tareas intentan incrementar un contador. Decide cómo se intercalan la lectura y la escritura, y protege después la sección crítica.
Contador compartido
0
Bloqueo: libre
Tarea A
Copia privada: sin leer
- 1. Leer contador → await
- 2. Escribir copia + 1
- 3. Terminada
Tarea B
Copia privada: sin leer
- 1. Leer contador → await
- 2. Escribir copia + 1
- 3. Terminada
Elige qué tarea ejecuta su siguiente operación.
- Aún no hay operaciones.
const copia = contador;
await pausa();
contador = copia + 1;JavaScript puede intercalar tareas alrededor de await aunque ejecute este código en un solo hilo. El bloqueo es conceptual: lectura y escritura permanecen protegidas incluso durante la espera. No crea hilos ni modifica datos externos.
Experimenta: Avanza A, B, A, B: el resultado es 1. Activa el bloqueo, repite y observa cómo B espera; al completar ambas tareas el resultado es 2.
Resumen del tema
Conceptos clave #
- Modelo Monohilo (Single-Threaded): JavaScript cuenta con un único hilo de ejecución principal en la pila de llamadas (Call Stack).
- Síncrono (Bloqueante): las operaciones se ejecutan secuencialmente de arriba a abajo, deteniendo el hilo hasta que cada una concluye.
- Asíncrono (No Bloqueante): las tareas pesadas de I/O (temporizadores
setTimeout, peticiones de redfetch, acceso a bases de datos) se delegan a las Web APIs/entorno, procesando sus respuestas en el bucle de eventos (Event Loop). - Evolución del Manejo Asíncrono: Callbacks Promesas (
.then(),.catch()) Sintaxis modernaasync/await.
Qué debes recordar #
El asincronismo en JavaScript evita congelar la interfaz o el hilo principal, delegando tareas lentas a través del Event Loop.