Web Workers i JavaScript

Web Workers i JavaScript

Den här artikeln förklarar Web Workers i 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 i JavaScript

Web Worker i JavaScript är en mekanism som gör det möjligt att köra kod i en separat tråd från huvudtråden. Detta möjliggör tunga beräkningar och långvariga operationer att utföras asynkront, vilket förhindrar att huvudtråden blockeras. Genom att använda Web Worker förbättras användargränssnittets responsivitet och applikationens prestanda.

Grundläggande användning av Web Worker

Låt oss titta på den grundläggande användningen av Web Worker.

En ny Web Worker skapas genom att ange en JavaScript-fil.

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};
  • Denna kod demonstrerar den grundläggande mekanismen för att använda en Web Worker för att begära beräkning från huvudtråden och ta emot resultatet asynkront. Den skickar 10 som ett meddelande till Web Worker och tar emot 20 som resultatmeddelande. Huvudtråden och Web Worker kommunicerar genom att skicka och ta emot meddelanden för att begära och ta emot bearbetningsresultat.

Grundläggande funktioner

Web Worker erbjuder följande grundläggande funktioner.

  • postMessage och onmessage Används för att skicka och ta emot meddelanden mellan huvudtråden och Web Worker. Skicka data med postMessage och ta emot det med onmessage.
  • Tråd-oberoende Web Worker fungerar helt oberoende av huvudtråden. Därför kan variabler och funktioner som definieras i huvudtråden inte nås. Nödvändiga data behöver skickas via postMessage.
  • Script-import För att ladda externa skript i en Web Worker, använd 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};

Alternativt kan du också använda import enligt exemplet nedan.

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};
  • Genom att ange type: 'module' i argumentet till new Worker kan du behandla workern som en ES-modul och använda import-syntaxen.

Skillnader mellan Web Worker och async-funktioner

Web Worker

Funktioner
  • Trådisolering Web Worker kör JavaScript-kod i en separat tråd. Detta möjliggör tung beräkning utan att blockera huvudtråden (UI-tråden).
  • Parallell bearbetning Att använda Web Worker gör det möjligt för JavaScript-program att utföra parallell bearbetning i flera trådar.
  • Meddelandekommunikation Web Worker och huvudtråden delar inte data direkt, utan utbyter meddelanden via postMessage och onmessage.
  • Kan inte komma åt UI Web Worker kan inte komma åt DOM, så den kan inte direkt manipulera UI.
Användningsfall
  • Den är lämplig för tunga beräkningsprocesser som bildbehandling, dataanalys och kryptering.
  • Den kan användas när du inte vill blockera huvudtråden.

async

Funktioner
  • Förenklar asynkron bearbetning async-funktionen är en syntax för att göra asynkron bearbetning mer läsbar och använder Promise internt.
  • Enkel tråd Alla async-funktioner körs på huvudtråden. Därför måste du hitta metoder för att undvika att blockera UI-tråden.
  • Optimalt för I/O-operationer Det passar för asynkrona uppgifter som nätverkskommunikation och filinläsning, men inte för tung beräkning.
Användningsfall
  • Det lämpar sig för nätverkskommunikation som API-anrop.
  • Det lämpar sig för filinläsning och -skrivning med hjälp av browser-API:er eller Node.js.

Huvudsakliga skillnader

Funktioner Web Worker async
Exekveringsmiljö Separat tråd Huvudtråd
Syfte Parallel bearbetning, avlastning av tunga beräkningar Kortfattad beskrivning av asynkrona operationer
DOM-åtkomst Inte möjligt Möjligt
Kommunikationsmetod Meddelandeöverföring (t.ex. postMessage) Inte nödvändig (hanteras via direkta funktionsanrop eller await)
Användningsområden Tidskrävande beräkningar, dataanalys I/O-operationer, API-anrop

När du ska använda varje

För CPU-intensiva uppgifter kan du använda Web Worker för att minska belastningen på huvudtråden. Å andra sidan, för nätverkskommunikation eller I/O-operationer kan du förenkla din kod med hjälp av async/await.

Genom att kombinera båda på ett lämpligt sätt kan du uppnå effektiv asynkron bearbetning.

Exempel på användning av Web Worker

Exempel på avlastning av tunga beräkningar

Härnäst följer ett exempel på att avlasta tunga beräkningar.

 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
  • Den här koden är ett exempel på att använda en Web Worker för att separera och utföra tunga uppgifter, såsom beräkning av Fibonaccital, från huvudtråden.

Ett exempel på att specificera ett uppgiftsnamn

Härnäst följer ett exempel på att skicka och ta emot meddelanden genom att specificera ett uppgiftsnamn.

 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 });
  • Den här koden är ett exempel på att dirigera bearbetning baserat på task-namnet i meddelandet, där Web Worker returnerar beräkningsresultat eller fel till huvudtråden tillsammans med uppgiftsnamnet.

Anteckningar

När du använder Web Worker, tänk på följande punkter.

  • Kan inte komma åt DOM Web Worker kan inte manipulera UI:t eller komma åt DOM. DOM-manipulation behöver utföras i huvudtråden.
  • Kommunikationsöverhead Det finns viss overhead vid datautbyte mellan huvudtråden och Web Worker. Detta kan påverka prestandan, särskilt vid frekvent utbyte av stora mängder data.
  • Same-Origin Policy Web Worker-skript lyder under same-origin policy. Skript kan inte laddas från olika domäner.

Att använda Web Worker kan förbättra prestandan och responsiviteten i din applikation, men det är viktigt att använda det på rätt sätt med tanke på begränsningar som oförmågan att manipulera DOM:en.

Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.

YouTube Video