Pekerja Web dalam JavaScript

Pekerja Web dalam JavaScript

Artikel ini menerangkan tentang Pekerja Web dalam 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 dalam JavaScript

Web Worker dalam JavaScript ialah satu mekanisme yang membolehkan kod dijalankan dalam benang (thread) yang berasingan daripada benang utama. Ini membolehkan pengiraan berat dan operasi jangka panjang dilakukan secara asinkron, mengelakkan thread utama daripada terhalang. Dengan menggunakan Web Worker, responsif antara muka pengguna bertambah baik dan prestasi aplikasi meningkat.

Penggunaan asas Web Worker

Mari kita lihat penggunaan asas Web Worker.

Web Worker baharu dicipta dengan menentukan fail 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};
  • Kod ini menunjukkan mekanisme asas penggunaan Web Worker untuk meminta pengiraan daripada benang utama dan menerima hasilnya secara asinkron. Ia menghantar 10 sebagai mesej kepada Web Worker dan menerima 20 sebagai mesej hasil. Benang utama dan Web Worker berkomunikasi dengan menghantar dan menerima mesej untuk meminta dan menerima hasil pemprosesan.

Fungsi asas

Web Worker menyediakan ciri-ciri asas berikut.

  • postMessage dan onmessage Digunakan untuk menghantar dan menerima mesej antara benang utama dan Web Worker. Hantar data dengan postMessage dan terima dengan onmessage.
  • Kebebasan Benang (Thread Independence) Web Worker beroperasi sepenuhnya secara bebas daripada benang utama. Oleh itu, pembolehubah dan fungsi yang ditakrif dalam thread utama tidak dapat diakses. Data yang diperlukan perlu dihantar melalui postMessage.
  • Import Skrip Untuk memuatkan skrip luaran dalam Web Worker, gunakan 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};

Sebagai alternatif, anda juga boleh menggunakan import seperti yang ditunjukkan di bawah.

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};
  • Dengan menetapkan type: 'module' dalam argumen new Worker, anda boleh menganggap worker itu sebagai modul ES dan menggunakan sintaks import.

Perbezaan antara Web Worker dan fungsi async

Web Worker

Ciri-ciri
  • Pengasingan Benang (Thread Isolation) Web Worker melaksanakan kod JavaScript dalam benang yang berasingan. Ini membolehkan pemprosesan pengiraan berat dilakukan tanpa menghalang benang utama (benang UI).
  • Pemprosesan Serentak (Concurrent Processing) Menggunakan Web Worker membolehkan program JavaScript melaksanakan pemprosesan serentak dalam berbilang benang.
  • Komunikasi Mesej Web Worker dan benang utama tidak berkongsi data secara langsung dan bertukar mesej menggunakan postMessage dan onmessage.
  • Tidak Boleh Akses UI Web Worker tidak boleh mengakses DOM, jadi ia tidak boleh memanipulasi UI secara langsung.
Kes penggunaan
  • Ia sesuai untuk proses pengiraan berat seperti pemprosesan imej, analisis data, dan penyulitan.
  • Ia boleh digunakan apabila anda tidak mahu menghalang benang utama.

async

Ciri-ciri
  • Memudahkan Pemprosesan Asinkron Fungsi async ialah satu sintaks untuk menjadikan pemprosesan asinkron lebih mudah dibaca, secara dalaman menggunakan Promise.
  • Benang Tunggal Semua fungsi async dijalankan pada benang utama. Oleh itu, anda perlu mencari cara untuk mengelakkan menghalang benang UI.
  • Optimum untuk Operasi I/O Ia sesuai untuk tugas asinkron seperti komunikasi rangkaian dan pembacaan fail, tetapi tidak sesuai untuk pengiraan berat.
Kes penggunaan
  • Ia sesuai untuk komunikasi rangkaian seperti panggilan API.
  • Ia sesuai untuk pembacaan dan penulisan fail menggunakan API pelayar atau Node.js.

Perbezaan Utama

Ciri-ciri Web Worker async
Persekitaran Pelaksanaan Utas berasingan Utas utama
Tujuan Pemprosesan selari, pengalihan pengiraan berat Penerangan ringkas mengenai operasi tak segerak
Akses DOM Tidak mungkin Mungkin
Kaedah Komunikasi Penghantaran mesej (contoh, postMessage) Tidak diperlukan (dikendalikan melalui panggilan fungsi terus atau await)
Kes Penggunaan Pengiraan yang memakan masa, analisis data Operasi I/O, panggilan API

Bila Untuk Menggunakan Setiap Satu

Untuk tugas yang intensif CPU, anda boleh menggunakan Web Worker untuk mengurangkan beban pada utas utama. Sebaliknya, untuk komunikasi rangkaian atau operasi I/O, anda boleh mempermudahkan kod anda menggunakan async/await.

Dengan menggabungkan kedua-duanya dengan sesuai, anda boleh mencapai pemprosesan tak segerak yang cekap.

Contoh Penggunaan Web Worker

Contoh melaksanakan pengiraan berat

Seterusnya ialah contoh memindahkan pengiraan berat.

 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
  • Kod ini adalah contoh penggunaan Web Worker untuk mengasingkan dan melaksanakan tugas berat seperti pengiraan jujukan Fibonacci dari benang utama.

Contoh penetapan nama tugas

Seterusnya adalah contoh menghantar dan menerima mesej dengan menentukan nama tugas.

 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 });
  • Kod ini adalah contoh pemprosesan berdasarkan nama task dalam mesej, di mana Web Worker memulangkan hasil pengiraan atau ralat ke benang utama bersama dengan nama tugas.

Nota

Apabila menggunakan Web Worker, ambil perhatian perkara-perkara berikut.

  • Tidak Boleh Akses DOM Web Worker tidak boleh memanipulasi UI atau mengakses DOM. Manipulasi DOM perlu dilakukan dalam thread utama.
  • Overhead Komunikasi Terdapat sedikit overhead semasa pertukaran data antara benang utama dan Web Worker. Ini boleh menjejaskan prestasi, terutamanya apabila sering bertukar sejumlah besar data.
  • Polisi Asal-Sama (Same-Origin Policy) Skrip Web Worker tertakluk kepada polisi asal-sama (same-origin policy). Skrip tidak boleh dimuat daripada domain yang berbeza.

Menggunakan Web Worker boleh meningkatkan prestasi dan responsif aplikasi anda, tetapi adalah penting untuk menggunakannya dengan sewajarnya dengan mempertimbangkan batasan seperti ketidakupayaan untuk memanipulasi DOM.

Anda boleh mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Sila lihat juga saluran YouTube kami.

YouTube Video