Web Workers in JavaScript

Web Workers in JavaScript

Dit artikel legt uit wat Web Workers in JavaScript zijn.

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 is een mechanisme waarmee code in een aparte thread kan draaien, los van de hoofdthread. Hierdoor kunnen zware berekeningen en langdurige operaties asynchroon worden uitgevoerd, waardoor de hoofdthread niet wordt geblokkeerd. Door gebruik te maken van Web Worker verbetert de responsiviteit van de gebruikersinterface en wordt de prestatie van de applicatie verbeterd.

Het basisgebruik van Web Worker

Laten we kijken naar het basisgebruik van Web Worker.

Een nieuwe Web Worker wordt aangemaakt door een JavaScript-bestand te specificeren.

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};
  • Deze code demonstreert het basismechanisme waarbij een Web Worker wordt gebruikt om berekeningen aan te vragen vanaf de hoofdthread en het resultaat asynchroon te ontvangen. Er wordt 10 als bericht naar de Web Worker gestuurd en 20 als resultaatbericht ontvangen. De hoofdthread en de Web Worker communiceren door berichten te verzenden en te ontvangen om verwerkingsresultaten aan te vragen en te ontvangen.

Basisfuncties

Web Worker biedt de volgende basisfuncties.

  • postMessage en onmessage Wordt gebruikt om berichten te versturen en te ontvangen tussen de hoofdthread en de Web Worker. Verzend gegevens met postMessage en ontvang deze met onmessage.
  • Thread-onafhankelijkheid Web Worker werkt volledig onafhankelijk van de hoofdthread. Daarom kunnen variabelen en functies die in de hoofdthread zijn gedefinieerd niet worden benaderd. Benodigde gegevens moeten worden doorgegeven via postMessage.
  • Scriptimport Om externe scripts te laden binnen een Web Worker, gebruik je 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};

Als alternatief kun je ook import gebruiken zoals hieronder getoond.

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};
  • Door type: 'module' te specificeren als argument van new Worker, kun je de worker als een ES-module behandelen en de import-syntax gebruiken.

Verschillen tussen Web Worker en async-functies

Web Worker

Kenmerken
  • Thread-isolatie Web Worker voert JavaScript-code uit in een aparte thread. Hierdoor kunnen zware berekeningen worden uitgevoerd zonder de hoofdthread (UI-thread) te blokkeren.
  • Gelijktijdige verwerking Met Web Worker kunnen JavaScript-programma’s gelijktijdige verwerking uitvoeren in meerdere threads.
  • Berichtcommunicatie De Web Worker en de hoofdthread delen geen data direct, maar wisselen berichten uit via postMessage en onmessage.
  • Geen toegang tot UI Web Worker heeft geen toegang tot de DOM, dus kan de UI niet direct manipuleren.
Gebruiksscenario's
  • Het is geschikt voor zware rekenprocessen zoals beeldverwerking, data-analyse en encryptie.
  • Het kan worden gebruikt wanneer u de hoofdthread niet wilt blokkeren.

async

Kenmerken
  • Vereenvoudigen van asynchrone verwerking De async-functie is een syntaxis die asynchrone verwerking leesbaarder maakt, waarbij intern gebruik wordt gemaakt van Promise.
  • Enkele thread Alle async-functies draaien op de hoofdthread. Daarom moet u methoden bedenken om te voorkomen dat de UI-thread wordt geblokkeerd.
  • Optimaal voor I/O-bewerkingen Het is geschikt voor asynchrone taken zoals netwerkcommunicatie en het lezen van bestanden, maar niet voor zware berekeningen.
Gebruiksscenario's
  • Het is geschikt voor netwerkcommunicatie zoals API-aanroepen.
  • Het is geschikt voor het lezen en schrijven van bestanden met behulp van browser-API's of Node.js.

Belangrijkste Verschillen

Kenmerken Web Worker async
Uitvoeringsomgeving Aparte thread Hoofdthread
Doel Parallelle verwerking, zware berekeningen ontlasten Beknopte beschrijving van asynchrone operaties
Toegang tot DOM Niet mogelijk Mogelijk
Communicatiemethode Berichtuitwisseling (bijv. postMessage) Niet nodig (afgehandeld via directe functieaanroepen of await)
Gebruikssituaties Tijdrovende berekeningen, data-analyse I/O-operaties, API-aanroepen

Wanneer Elke Te Gebruiken Is

Voor CPU-intensieve taken kun je Web Worker gebruiken om de belasting van de hoofdthread te verminderen. Aan de andere kant kun je voor netwerkcommunicatie of I/O-operaties je code vereenvoudigen met async/await.

Door beide op de juiste manier te combineren, kun je efficiënte asynchrone verwerking bereiken.

Voorbeelden van het Gebruik van Web Worker

Voorbeeld van het uitbesteden van zware berekeningen

Hieronder volgt een voorbeeld van het uitbesteden van zware berekeningen.

 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
  • Deze code is een voorbeeld van het gebruik van een Web Worker om zware taken, zoals het berekenen van de Fibonaccireeks, van de hoofdthread te scheiden en uit te voeren.

Een voorbeeld van het specificeren van een taaknaam

Hieronder volgt een voorbeeld van het verzenden en ontvangen van berichten door een taaknaam te specificeren.

 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 });
  • Deze code is een voorbeeld van het verwerken op basis van de task-naam in het bericht, waarbij de Web Worker de berekeningsresultaten of fouten samen met de taaknaam terugstuurt naar de hoofdthread.

Notities

Houd rekening met de volgende punten bij het gebruik van Web Worker.

  • Geen toegang tot DOM Web Worker kan de UI niet manipuleren of de DOM benaderen. DOM-manipulaties moeten worden uitgevoerd in de hoofdthread.
  • Communicatie-overhead Er is enige overhead bij het uitwisselen van gegevens tussen de hoofdthread en de Web Worker. Dit kan invloed hebben op de prestaties, vooral bij het frequent uitwisselen van grote hoeveelheden gegevens.
  • Same-origin-beleid Web Worker-scripts zijn onderhevig aan het same-origin-beleid. Scripts kunnen niet van verschillende domeinen worden geladen.

Het gebruik van Web Worker kan de prestaties en responsiviteit van je applicatie verbeteren, maar het is belangrijk dit op de juiste manier te gebruiken, rekening houdend met beperkingen zoals het onvermogen om de DOM te manipuleren.

Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.

YouTube Video