I Web Worker in JavaScript

I Web Worker in JavaScript

Questo articolo spiega cosa sono i Web Worker in JavaScript.

YouTube Video

javascript-web-worker.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; 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 in JavaScript

Web Worker in JavaScript è un meccanismo che consente al codice di essere eseguito in un thread separato dal thread principale. Questo consente di eseguire calcoli complessi e operazioni di lunga durata in modo asincrono, evitando il blocco del thread principale. Usando i Web Worker, la reattività dell'interfaccia utente migliora e le prestazioni dell'applicazione aumentano.

L'uso di base dei Web Worker

Vediamo l'utilizzo di base di Web Worker.

Un nuovo Web Worker viene creato specificando un file 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};
  • Questo codice dimostra il meccanismo di base per utilizzare un Web Worker per richiedere un calcolo dal thread principale e ricevere il risultato in modo asincrono. Invia 10 come messaggio al Web Worker e riceve 20 come messaggio di risultato. Il thread principale e il Web Worker comunicano inviando e ricevendo messaggi per richiedere e ottenere i risultati dell'elaborazione.

Funzioni di base

Web Worker offre le seguenti funzionalità di base.

  • postMessage e onmessage Utilizzato per inviare e ricevere messaggi tra il thread principale e il Web Worker. Invia dati con postMessage e ricevili con onmessage.
  • Indipendenza del Thread Web Worker funziona in modo completamente indipendente dal thread principale. Di conseguenza, non è possibile accedere alle variabili e alle funzioni definite nel thread principale. I dati richiesti devono essere passati tramite postMessage.
  • Importazione di Script Per caricare script esterni all'interno di un Web Worker, utilizzare importScripts().
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};

In alternativa, è possibile utilizzare anche import come mostrato di seguito.

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};
  • Specificando type: 'module' nell'argomento di new Worker, è possibile trattare il worker come un modulo ES e utilizzare la sintassi import.

Differenze tra Web Worker e funzioni async

Web Worker

Caratteristiche
  • Isolamento del Thread Web Worker esegue il codice JavaScript in un thread separato. Questo consente di eseguire elaborazioni di calcolo pesanti senza bloccare il thread principale (thread UI).
  • Elaborazione Concorrente Usare Web Worker permette ai programmi JavaScript di eseguire elaborazioni concorrenti su più thread.
  • Comunicazione tramite Messaggi Il Web Worker e il thread principale non condividono direttamente i dati e scambiano messaggi tramite postMessage e onmessage.
  • Impossibile Accedere alla UI Web Worker non può accedere al DOM, quindi non può manipolare direttamente l'interfaccia utente (UI).
Casi d'uso
  • È adatto per processi di calcolo pesante come l'elaborazione delle immagini, l'analisi dei dati e la crittografia.
  • Può essere utilizzato quando non si desidera bloccare il thread principale.

async

Caratteristiche
  • Semplificazione dell'Elaborazione Asincrona La funzione async è una sintassi per rendere più leggibile l'elaborazione asincrona, utilizzando internamente Promise.
  • Thread Singolo Tutte le funzioni async vengono eseguite sul thread principale. Pertanto, è necessario trovare soluzioni per evitare di bloccare il thread UI.
  • Ottimale per Operazioni di I/O È adatto per attività asincrone come comunicazione di rete e lettura di file, ma non per calcoli pesanti.
Casi d'uso
  • È adatto per la comunicazione di rete come le chiamate API.
  • È adatto per la lettura e scrittura di file tramite API del browser o Node.js.

Differenze principali

Caratteristiche Web Worker async
Ambiente di esecuzione Thread separato Thread principale
Scopo Elaborazione parallela, gestione di calcoli intensivi Descrizione concisa delle operazioni asincrone
Accesso al DOM Non possibile Possibile
Metodo di comunicazione Passaggio di messaggi (es. postMessage) Non richiesto (gestito tramite chiamate di funzione dirette o await)
Casi d'uso Calcoli a lungo termine, analisi dei dati Operazioni di I/O, chiamate API

Quando utilizzare ciascuno

Per compiti che richiedono un utilizzo intensivo della CPU, è possibile utilizzare i Web Worker per ridurre il carico sul thread principale. D'altro canto, per la comunicazione di rete o le operazioni di I/O, è possibile semplificare il codice utilizzando async/await.

Combinandoli in modo appropriato, è possibile ottenere un'elaborazione asincrona efficiente.

Esempi di utilizzo di Web Worker

Esempio di trasferimento di calcoli complessi

Di seguito è riportato un esempio di delega dei calcoli pesanti.

 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
  • Questo codice è un esempio di utilizzo di un Web Worker per separare ed eseguire attività pesanti, come il calcolo della sequenza di Fibonacci, dal thread principale.

Un esempio di specifica del nome di un compito

Segue un esempio di invio e ricezione di messaggi specificando il nome di un compito.

 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 });
  • Questo codice è un esempio di elaborazione in base al nome del task nel messaggio, in cui il Web Worker restituisce i risultati del calcolo o eventuali errori al thread principale insieme al nome del compito.

Note

Quando si utilizza Web Worker, tenere presenti i seguenti punti.

  • Impossibile Accedere al DOM Web Worker non può manipolare l'interfaccia utente né accedere al DOM. La manipolazione del DOM deve essere eseguita nel thread principale.
  • Overhead della Comunicazione C'è un certo overhead quando si scambiano dati tra il thread principale e il Web Worker. Questo può influire sulle prestazioni, specialmente quando si scambiano grandi quantità di dati frequentemente.
  • Politica della Stessa Origine Gli script Web Worker sono soggetti alla politica della stessa origine. Gli script non possono essere caricati da domini diversi.

L'uso dei Web Worker può migliorare le prestazioni e la reattività della tua applicazione, ma è importante utilizzarli in modo appropriato considerando limitazioni come l'impossibilità di manipolare il DOM.

Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.

YouTube Video