Los programadores de JavaScript están acostumbrados a fingir el paralelismo, pero hay una manera de lograr el verdadero paralelismo que deberías usar ahora mismo.
JavaScript puede tener problemas con las tareas de alto rendimiento porque es un lenguaje de un solo subproceso. Con el paralelismo, puede lograr una ejecución multiproceso en JavaScript y mejorar el rendimiento y la capacidad de respuesta de sus aplicaciones web modernas.
Paralelismo en la programación de JavaScript
El paralelismo es crucial en la informática moderna para mejorar el rendimiento y la escalabilidad. Lo hace mediante la utilización eficaz de los recursos disponibles.
Una técnica común utilizada para lograr el paralelismo en la programación es el subproceso múltiple. El subproceso de JavaScript, sin embargo, es un sistema de un solo subproceso y solo puede manejar una tarea a la vez. Esto significa que no está familiarizado con las ejecuciones de programas en paralelo.
JavaScript falsifica la programación paralela
Un concepto erróneo común sobre el paralelismo es que puede lograrlo usando técnicas de programación asíncrona como async/await, devoluciones de llamada y promesas:
// Función asíncrona/espera que simula una solicitud de red
asíncronofunciónobtener datos() {
constante respuesta = esperar buscar();
constante datos = esperar respuesta.json();
devolver datos;
}// Función de devolución de llamada que registra los datos obtenidos en la consola
funciónDato de registro(datos) {
consola.Dato de registro);
}// Método Promise.all() que ejecuta múltiples promesas en paralelo
Promesa.todo([
obtener datos(),
obtener datos(),
]).entonces((resultados) => {
consola.log (resultados);
});
// Llamar a la función fetchData y pasar la función logData como devolución de llamada
buscarDatos().entonces (datosderegistro);
Estas técnicas en realidad no ejecutan código en paralelo. JavaScript usa el bucle de eventos para imitar la programación paralela dentro de su diseño de un solo hilo.
El bucle de eventos es una parte fundamental del entorno de tiempo de ejecución de JavaScript. Le permite ejecutar operaciones asincrónicas, como solicitudes de red, en segundo plano sin bloquear el único hilo principal.
El bucle de eventos comprueba constantemente si hay nuevos eventos o tareas en una cola y los ejecuta uno por uno secuencialmente. Esta técnica permite que JavaScript logre concurrencia y paralelismo teórico.
Concurrencia vs. Paralelismo
La concurrencia y el paralelismo a menudo se malinterpretan y se intercambian en el mundo de JavaScript.
La concurrencia en JavaScript se refiere a la capacidad de ejecutar múltiples tareas superponiendo la ejecución de las tareas. Donde una tarea puede comenzar antes de que otra se complete, pero las tareas no pueden comenzar ni terminar simultáneamente. Esto permite que JavaScript maneje operaciones de manera eficiente, como obtener datos de una API REST o leer archivos, sin bloquear el hilo de ejecución principal.
El paralelismo, por otro lado, se refiere a la capacidad de ejecutar múltiples tareas simultáneamente a través de múltiples hilos. Estos subprocesos en segundo plano pueden ejecutar tareas de forma independiente y simultánea. Esto abre oportunidades para lograr un verdadero paralelismo en las aplicaciones de JavaScript.
Las aplicaciones de JavaScript pueden lograr un verdadero paralelismo a través de el uso de Web Workers.
Los trabajadores web introducen el paralelismo en JavaScript
Los trabajadores web son una característica de los navegadores web modernos que permiten que el código JavaScript se ejecute en subprocesos en segundo plano, separados del subproceso de ejecución principal. A diferencia del hilo principal, que maneja las interacciones del usuario y las actualizaciones de la interfaz de usuario. El Web Worker se dedicaría a realizar tareas computacionalmente intensivas.
A continuación se muestra un diagrama que representa el funcionamiento de un Web Worker en JavaScript.
El subproceso principal y Web Worker pueden comunicarse mediante el paso de mensajes. Utilizando el postMensaje método para enviar mensajes y el enmensaje controlador de eventos para recibir mensajes, puede pasar instrucciones o datos de un lado a otro.
Creación de un trabajador web
Para crear un Web Worker, debe crear un archivo JavaScript separado.
Aquí hay un ejemplo:
// principal.js// Crear un nuevo trabajador web
constante trabajador = nuevo Obrero('trabajador.js');
// Enviar un mensaje al Web Worker
trabajador.postMessage('¡Hola desde el hilo principal!');
// Escuche los mensajes del Web Worker
trabajador.enmensaje = función(evento) {
consola.registro('Mensaje recibido de Web Worker:', evento.datos);
};
El ejemplo anterior crea un nuevo Web Worker pasando la ruta al script del trabajador (trabajador.js) como argumento de la Obrero constructor. Puede enviar un mensaje al Web Worker usando el postMensaje método y escuche los mensajes del Web Worker usando el enmensaje controlador de eventos.
A continuación, debe crear el script de trabajo (trabajador.js) archivo:
// trabajador.js
// Escuche los mensajes del hilo principal
self.onmessage = función(evento) {
consola.registro('Mensaje recibido del hilo principal:', evento.datos);
// Enviar un mensaje de vuelta al hilo principal
self.postMessage("¡Hola de trabajador.js!");
};
El script de Web Worker escucha los mensajes del hilo principal usando el enmensaje controlador de eventos. Al recibir un mensaje, cierra la sesión del mensaje dentro evento.datos y enviar un nuevo mensaje al hilo principal con el postMensaje método.
Aprovechar el paralelismo con trabajadores web
El caso de uso principal de Web Workers es la ejecución de tareas de JavaScript intensivas en computación en paralelo. Al descargar estas tareas a Web Workers, puede lograr mejoras significativas en el rendimiento.
Aquí hay un ejemplo del uso de un trabajador web para realizar un cálculo pesado:
// principal.jsconstante trabajador = nuevo Obrero('trabajador.js');
// Enviar datos al Web Worker para el cálculo
trabajador.postMessage([1, 2, 3, 4, 5]);
// Escuche el resultado del Web Worker
trabajador.enmensaje = función(evento) {
constante resultado = evento.datos;
consola.registro('Resultado del cálculo:', resultado);
};
Trabajador.js:
// Escuche los datos del hilo principal
self.onmessage = función (evento) {
constante numeros = evento.datos;constante resultado = realizar cálculo pesado (números);
// Enviar el resultado de vuelta al hilo principal
self.postMessage (resultado);
};
funciónperformHeavyCalculation(datos) {
// Realiza un cálculo complejo en la matriz de números
devolver datos
.mapa((número) =>Matemáticas.pow (número, 3)) // Cubo de cada número
.filtrar((número) => número % 20) // Filtra números pares
.reducir((suma, numero) => suma + número, 0); // Suma todos los números
}
En este ejemplo, pasa una matriz de números del subproceso principal al Web Worker. Web Worker realiza el cálculo utilizando la matriz de datos proporcionada y envía el resultado al subproceso principal. El realizar cálculo pesado () La función asigna cada número a su cubo, filtra los números pares y finalmente los suma.
Limitaciones y Consideraciones
Si bien Web Workers proporciona un mecanismo para lograr el paralelismo en JavaScript, es importante tener en cuenta algunas limitaciones y consideraciones:
- Sin memoria compartida: Web Workers opera en subprocesos separados y no comparte memoria con el subproceso principal. Por lo tanto, no pueden acceder directamente a variables u objetos desde el hilo principal sin pasar mensajes.
- Serialización y deserialización: Al pasar datos entre el subproceso principal y Web Workers, debe serializar y deserializar los datos, ya que el paso de mensajes es una comunicación basada en texto. Este proceso incurre en un costo de rendimiento y puede afectar el rendimiento general de la aplicación.
- Compatibilidad con navegador: Aunque Web Workers es compatible con la mayoría de los navegadores web modernos, algunos navegadores más antiguos o entornos limitados pueden tener soporte parcial o nulo para Web Workers.
Logre un verdadero paralelismo en JavaScript
El paralelismo en JavaScript es un concepto interesante que permite una verdadera ejecución simultánea de tareas, incluso en un lenguaje principalmente de subproceso único. Con la introducción de Web Workers, puede aprovechar el poder del paralelismo y lograr mejoras significativas en el rendimiento de sus aplicaciones JavaScript.