Trabajadores Web en JavaScript
Este artículo explica los Web Workers en JavaScript.
YouTube Video
javascript-web-worker.html
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>JavaScript & HTML</title>
6 <style>
7 * {
8 box-sizing: border-box;
9 }
10
11 body {
12 margin: 0;
13 padding: 1em;
14 padding-bottom: 10em;
15 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16 background-color: #f7f9fc;
17 color: #333;
18 line-height: 1.6;
19 }
20
21 .container {
22 max-width: 800px;
23 margin: 0 auto;
24 padding: 1em;
25 background-color: #ffffff;
26 border: 1px solid #ccc;
27 border-radius: 10px;
28 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
29 }
30
31 .container-flex {
32 display: flex;
33 flex-wrap: wrap;
34 gap: 2em;
35 max-width: 1000px;
36 margin: 0 auto;
37 padding: 1em;
38 background-color: #ffffff;
39 border: 1px solid #ccc;
40 border-radius: 10px;
41 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
42 }
43
44 .left-column, .right-column {
45 flex: 1 1 200px;
46 min-width: 200px;
47 }
48
49 h1, h2 {
50 font-size: 1.2rem;
51 color: #007bff;
52 margin-top: 0.5em;
53 margin-bottom: 0.5em;
54 border-left: 5px solid #007bff;
55 padding-left: 0.6em;
56 background-color: #e9f2ff;
57 }
58
59 button {
60 display: block;
61 margin: 1em auto;
62 padding: 0.75em 1.5em;
63 font-size: 1rem;
64 background-color: #007bff;
65 color: white;
66 border: none;
67 border-radius: 6px;
68 cursor: pointer;
69 transition: background-color 0.3s ease;
70 }
71
72 button:hover {
73 background-color: #0056b3;
74 }
75
76 #output {
77 margin-top: 1em;
78 background-color: #1e1e1e;
79 color: #0f0;
80 padding: 1em;
81 border-radius: 8px;
82 min-height: 200px;
83 font-family: Consolas, monospace;
84 font-size: 0.95rem;
85 overflow-y: auto;
86 white-space: pre-wrap;
87 }
88
89 .highlight {
90 outline: 3px solid #ffc107; /* yellow border */
91 background-color: #fff8e1; /* soft yellow background */
92 transition: background-color 0.3s ease, outline 0.3s ease;
93 }
94
95 .active {
96 background-color: #28a745; /* green background */
97 color: #fff;
98 box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
99 transition: background-color 0.3s ease, box-shadow 0.3s ease;
100 }
101 </style>
102</head>
103<body>
104 <div class="container">
105 <h1>JavaScript Console</h1>
106 <button id="executeBtn">Execute</button>
107 <div id="output"></div>
108 </div>
109
110 <script>
111 // Override console.log to display messages in the #output element
112 (function () {
113 // Override console.log
114 const originalLog = console.log;
115 console.log = function (...args) {
116 originalLog.apply(console, args);
117 const message = document.createElement('div');
118 message.textContent = args.map(String).join(' ');
119 output.appendChild(message);
120 };
121
122 // Override console.error
123 const originalError = console.error;
124 console.error = function (...args) {
125 originalError.apply(console, args);
126 const message = document.createElement('div');
127 message.textContent = args.map(String).join(' ');
128 message.style.color = 'red'; // Color error messages red
129 output.appendChild(message);
130 };
131 })();
132
133 document.getElementById('executeBtn').addEventListener('click', () => {
134 // Prevent multiple loads
135 if (document.getElementById('externalScript')) return;
136
137 const script = document.createElement('script');
138 script.src = 'javascript-web-worker.js';
139 script.id = 'externalScript';
140 //script.onload = () => console.log('javascript-web-worker.js loaded and executed.');
141 //script.onerror = () => console.log('Failed to load javascript-web-worker.js.');
142 document.body.appendChild(script);
143 });
144 </script>
145</body>
146</html>
Web Worker
en JavaScript
Web Worker
en JavaScript es un mecanismo que permite ejecutar código en un hilo separado del hilo principal. Esto permite realizar cálculos intensivos y operaciones de larga duración de manera asincrónica, evitando que el hilo principal se bloquee. Al usar Web Worker
, mejora la capacidad de respuesta de la interfaz de usuario y se incrementa el rendimiento de la aplicación.
El uso básico de Web Worker
Veamos el uso básico de Web Worker
.
Se crea un nuevo Web Worker
especificando un archivo JavaScript.
1// worker.js (created as a separate file)
2onmessage = function(event) {
3 // Receive a message
4 const data = event.data;
5 // Perform heavy computation or processing
6 const result = data * 2;
7 // Return the result to the main thread
8 postMessage(result);
9};
1// Main thread (main.js)
2const worker = new Worker('worker.js');
3
4// Send a message to the worker
5worker.postMessage(10);
6
7// Receive a message from the worker
8worker.onmessage = function(event) {
9 console.log('Result from Worker: ', event.data); // Result: 20
10};
11
12// Error handling
13worker.onerror = function(error) {
14 console.error('Worker error: ', error);
15};
- Este código demuestra el mecanismo básico de usar un
Web Worker
para solicitar cálculos desde el hilo principal y recibir el resultado de forma asíncrona. Envía10
como mensaje alWeb Worker
y recibe20
como mensaje de resultado. El hilo principal y elWeb Worker
se comunican enviando y recibiendo mensajes para solicitar y recibir resultados de procesamiento.
Funciones básicas
Web Worker
proporciona las siguientes funcionalidades básicas.
postMessage
yonmessage
Se usan para enviar y recibir mensajes entre el hilo principal y elWeb Worker
. Envía datos conpostMessage
y recíbelos cononmessage
.- Independencia de hilos
Web Worker
funciona de manera completamente independiente del hilo principal. Por lo tanto, no se puede acceder a las variables y funciones definidas en el hilo principal. Los datos necesarios deben pasarse mediantepostMessage
. - Importación de scripts
Para cargar scripts externos dentro de un
Web Worker
, utilizaimportScripts()
.
1// mathUtils.js
2function double(n) {
3 return n * 2;
4}
1// worker.js
2importScripts('mathUtils.js');
3
4onmessage = function(event) {
5 const input = event.data;
6 const result = double(input); // mathUtils.jsの関数を使用
7 postMessage(result);
8};
1// Main thread (main.js)
2const worker = new Worker('worker.js');
3
4// Send a message to the worker
5worker.postMessage(10);
6
7// Receive a message from the worker
8worker.onmessage = function(event) {
9 console.log('Result from Worker: ', event.data); // Result: 20
10};
11
12// Error handling
13worker.onerror = function(error) {
14 console.error('Worker error: ', error);
15};
Alternativamente, también puedes usar import
como se muestra a continuación.
1// lib.js
2
3// Simulated CPU-intensive task
4export function doHeavyWork(n) {
5 return n * 2;
6}
1// worker.js
2import { doHeavyWork } from './lib.js';
3
4self.onmessage = (event) => {
5 const data = event.data;
6 const result = doHeavyWork(data);
7 self.postMessage(result);
8};
1// Main thread (main.js)
2const worker = new Worker('worker.js', { type: 'module' });
3
4// Send a message to the worker
5worker.postMessage(10);
6
7// Receive a message from the worker
8worker.onmessage = function(event) {
9 console.log('Result from Worker: ', event.data); // Result: 20
10};
11
12// Error handling
13worker.onerror = function(error) {
14 console.error('Worker error: ', error);
15};
- Especificando
type: 'module'
en el argumento denew Worker
, puedes tratar el worker como un módulo ES y utilizar la sintaxis deimport
.
Diferencias entre Web Worker
y las funciones async
Web Worker
Características
- Aislamiento de hilos
Web Worker
ejecuta código JavaScript en un hilo separado. Esto permite realizar procesamientos computacionales pesados sin bloquear el hilo principal (hilo de la UI). - Procesamiento concurrente
El uso de
Web Worker
permite a los programas JavaScript realizar procesamiento concurrente en varios hilos. - Comunicación por mensajes
El
Web Worker
y el hilo principal no comparten datos directamente y se comunican intercambiando mensajes mediantepostMessage
yonmessage
. - No puede acceder a la interfaz de usuario
Web Worker
no puede acceder al DOM, por lo que no puede manipular la interfaz de usuario directamente.
Casos de uso
- Es adecuado para procesos computacionales pesados, como procesamiento de imágenes, análisis de datos y encriptación.
- Se puede utilizar cuando no deseas bloquear el hilo principal.
async
Características
- Simplificando el procesamiento asíncrono
La función
async
es una sintaxis que hace el procesamiento asíncrono más legible, usando internamentePromise
. - Un solo hilo
Todas las funciones
async
se ejecutan en el hilo principal. Por lo tanto, necesitas idear formas para evitar bloquear el hilo de la UI. - Óptimo para operaciones de E/S Es adecuado para tareas asíncronas como la comunicación de red y la lectura de archivos, pero no para cálculos pesados.
Casos de uso
- Es adecuado para la comunicación de red como las llamadas a API.
- Es adecuado para la lectura y escritura de archivos usando APIs del navegador o Node.js.
Diferencias clave
Características | Web Worker | async |
---|---|---|
Entorno de Ejecución | Hilo separado | Hilo principal |
Propósito | Procesamiento en paralelo, descarga de cálculos pesados | Descripción concisa de las operaciones asíncronas |
Acceso al DOM | No posible | Posible |
Método de Comunicación | Paso de mensajes (por ejemplo, postMessage ) |
No requerido (gestionado mediante llamadas directas a funciones o await ) |
Casos de Uso | Cálculos que consumen mucho tiempo, análisis de datos | Operaciones de E/S, llamadas API |
Cuándo Usar Cada Uno
Para tareas intensivas en CPU, puedes usar Web Worker
para reducir la carga en el hilo principal. Por otro lado, para la comunicación en red u operaciones de E/S, puedes simplificar tu código usando async
/await
.
Al combinar ambos de manera apropiada, puedes lograr un procesamiento asíncrono eficiente.
Ejemplos del Uso de Web Worker
Ejemplo de descarga de cálculos complejos
A continuación se muestra un ejemplo de descarga de cálculos pesados.
1// worker.js
2onmessage = function(event) {
3 const num = event.data;
4 const result = fibonacci(num);
5 postMessage(result);
6};
7
8function fibonacci(n) {
9 if (n <= 1) return n;
10 return fibonacci(n - 1) + fibonacci(n - 2);
11}
1// Main thread
2const worker = new Worker('worker.js');
3
4worker.onmessage = function(event) {
5 console.log('Fibonacci result: ', event.data);
6};
7
8worker.postMessage(40); // Delegate heavy computation to the worker
- Este código es un ejemplo de cómo utilizar un Web Worker para separar y ejecutar tareas pesadas como los cálculos de la secuencia de Fibonacci fuera del hilo principal.
Un ejemplo de cómo especificar el nombre de una tarea
A continuación se muestra un ejemplo de cómo enviar y recibir mensajes especificando el nombre de una tarea.
1// worker.js
2self.onmessage = function(event) {
3 switch (event.data.task) {
4 case 'add':
5 const result = event.data.a + event.data.b;
6 self.postMessage({ task: 'result', value: result });
7 break;
8 default:
9 self.postMessage({ task: 'error', message: 'Invalid Task' });
10 }
11};
1// Main thread
2const worker = new Worker('worker.js');
3
4worker.onmessage = function(event) {
5 switch (event.data.task) {
6 case 'result':
7 console.log('Task result: ', event.data.value);
8 break;
9 case 'error':
10 console.error('Error: ', event.data.message);
11 break;
12 }
13};
14
15worker.postMessage({ task: 'add', a: 10, b: 20 });
- Este código es un ejemplo de cómo despachar el procesamiento en función del nombre de la
tarea
en el mensaje, con elWeb Worker
devolviendo los resultados de los cálculos o errores al hilo principal junto con el nombre de la tarea.
Notas
Cuando uses Web Worker
, ten en cuenta los siguientes puntos.
- No puede acceder al DOM
Web Worker
no puede manipular la interfaz de usuario ni acceder al DOM. La manipulación del DOM debe realizarse en el hilo principal. - Sobrecarga de comunicación
Existe cierta sobrecarga al intercambiar datos entre el hilo principal y el
Web Worker
. Esto puede afectar el rendimiento, especialmente cuando se intercambian grandes cantidades de datos con frecuencia. - Política del mismo origen
Los scripts de
Web Worker
están sujetos a la política del mismo origen. No se pueden cargar scripts desde dominios diferentes.
El uso de Web Worker
puede mejorar el rendimiento y la capacidad de respuesta de tu aplicación, pero es importante usarlo adecuadamente teniendo en cuenta limitaciones como la incapacidad de manipular el DOM.
Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.