Travailleurs Web en JavaScript

Travailleurs Web en JavaScript

Cet article explique les Travailleurs Web 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 &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 en JavaScript

Un Web Worker en JavaScript est un mécanisme qui permet d’exécuter du code dans un thread séparé du thread principal. Cela permet d'exécuter des calculs lourds et des opérations de longue durée de manière asynchrone, empêchant le blocage du thread principal. En utilisant Web Worker, la réactivité de l'interface utilisateur s'améliore et les performances de l'application augmentent.

L'utilisation de base de Web Worker

Jetons un œil à l’utilisation de base d’un Web Worker.

Un nouveau Web Worker est créé en spécifiant un fichier 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};
  • Ce code démontre le mécanisme de base d’utilisation d’un Web Worker pour demander un calcul depuis le thread principal et recevoir le résultat de manière asynchrone. Il envoie 10 comme message au Web Worker et reçoit 20 comme message de résultat. Le thread principal et le Web Worker communiquent en envoyant et en recevant des messages afin de demander et de recevoir des résultats de traitement.

Fonctions de base

Le Web Worker offre les fonctionnalités de base suivantes :.

  • postMessage et onmessage Utilisé pour envoyer et recevoir des messages entre le thread principal et le Web Worker. Envoyez des données avec postMessage et recevez-les avec onmessage.
  • Indépendance des threads Le Web Worker fonctionne de manière totalement indépendante du thread principal. Par conséquent, les variables et fonctions définies dans le thread principal ne sont pas accessibles. Les données nécessaires doivent être transmises via postMessage.
  • Importation de scripts Pour charger des scripts externes dans un Web Worker, utilisez 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};

Vous pouvez également utiliser import comme montré ci-dessous.

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};
  • En spécifiant type: 'module' dans l’argument de new Worker, vous pouvez traiter le worker comme un module ES et utiliser la syntaxe import.

Différences entre Web Worker et les fonctions async

Web Worker

Caractéristiques
  • Isolation des threads Le Web Worker exécute le code JavaScript dans un thread séparé. Cela permet d’effectuer des calculs lourds sans bloquer le thread principal (thread UI).
  • Traitement concurrent L’utilisation d’un Web Worker permet aux programmes JavaScript d’effectuer un traitement concurrent dans plusieurs threads.
  • Communication par message Le Web Worker et le thread principal ne partagent pas directement les données et échangent des messages via postMessage et onmessage.
  • Pas d’accès à l’UI Le Web Worker n’a pas accès au DOM et ne peut donc pas manipuler directement l’interface utilisateur.
Cas d'utilisation
  • Il est adapté aux processus de calcul lourds tels que le traitement d'image, l'analyse de données et le cryptage.
  • Il peut être utilisé lorsque vous ne voulez pas bloquer le thread principal.

async

Caractéristiques
  • Simplification du traitement asynchrone La fonction async est une syntaxe qui rend le traitement asynchrone plus lisible, utilisant en interne les Promise.
  • Thread unique Toutes les fonctions async s’exécutent sur le thread principal. Par conséquent, vous devez trouver des moyens d'éviter de bloquer le thread UI.
  • Optimal pour les opérations d’E/S Il convient aux tâches asynchrones comme la communication réseau et la lecture de fichiers, mais pas aux calculs intensifs.
Cas d'utilisation
  • Il est adapté à la communication réseau, comme les appels d’API.
  • Il convient à la lecture et à l’écriture de fichiers à l’aide des API du navigateur ou de Node.js.

Différences Clés

Caractéristiques Web Worker async
Environnement d'Exécution Thread séparé Thread principal
Objectif Traitement parallèle, délestage des calculs lourds Description concise des opérations asynchrones
Accès au DOM Impossible Possible
Méthode de Communication Échange de messages (par ex., postMessage) Pas nécessaire (géré via des appels de fonctions directs ou await)
Cas d'Utilisation Calculs gourmands en temps, analyse de données Opérations d'I/O, appels d'API

Quand Utiliser Chaque Méthode

Pour les tâches gourmandes en CPU, vous pouvez utiliser un Web Worker pour réduire la charge sur le thread principal. D'autre part, pour les communications réseau ou les opérations d'I/O, vous pouvez simplifier votre code en utilisant async/await.

En combinant les deux méthodes de manière appropriée, vous pouvez obtenir un traitement asynchrone efficace.

Exemples d'Utilisation de Web Worker

Exemple de délestage de calculs lourds

Voici un exemple de délestage de calculs intensifs.

 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
  • Ce code est un exemple d'utilisation d'un Web Worker pour séparer et exécuter des tâches lourdes comme le calcul de la suite de Fibonacci en dehors du thread principal.

Un exemple de spécification d'un nom de tâche

Voici un exemple d'envoi et de réception de messages en spécifiant un nom de tâche.

 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 });
  • Ce code est un exemple de distribution du traitement en fonction du nom de la tâche (task) dans le message, où le Web Worker retourne les résultats de calcul ou les erreurs au thread principal avec le nom de la tâche.

Notes

Lorsque vous utilisez un Web Worker, gardez les points suivants à l’esprit :.

  • Pas d’accès au DOM Le Web Worker ne peut pas manipuler l’interface utilisateur ni accéder au DOM. La manipulation du DOM doit être effectuée dans le thread principal.
  • Surcharge de communication Il existe une certaine surcharge lors de l’échange de données entre le thread principal et le Web Worker. Cela peut affecter les performances, en particulier lors de l'échange fréquent de grandes quantités de données.
  • Politique de même origine Les scripts de Web Worker sont soumis à la politique de même origine. Les scripts ne peuvent pas être chargés à partir de domaines différents.

Utiliser un Web Worker peut améliorer les performances et la réactivité de votre application, mais il est important de l'utiliser de manière appropriée en tenant compte des contraintes telles que l'incapacité de manipuler le DOM.

Vous pouvez suivre l'article ci-dessus avec Visual Studio Code sur notre chaîne YouTube. Veuillez également consulter la chaîne YouTube.

YouTube Video