Web Worker ใน TypeScript
บทความนี้อธิบายเกี่ยวกับ Web Workers ใน TypeScript
คุณสามารถเรียนรู้แนวคิดของ Web Workers และเคล็ดลับการใช้งานต่าง ๆ พร้อมตัวอย่าง
YouTube Video
Worker ใน TypeScript
ใน TypeScript, Worker เป็นกลไกสำหรับการประมวลผลในเบื้องหลังที่แยกจากเธรดหลัก โดยอาศัย JavaScript Web Workers API สิ่งนี้ช่วยให้การคำนวณที่ซับซ้อนและงานแบบ asynchronous ดำเนินการได้โดยไม่กระทบกับการทำงานของอินเทอร์เฟซผู้ใช้
Worker ทำงานแบบขนานกับเธรดหลัก (UI thread) และสามารถแลกเปลี่ยนข้อมูลระหว่างเธรดผ่านข้อความ แม้ใน TypeScript, คุณก็สามารถใช้ Worker ได้ในขณะที่เขียนโค้ดอย่างปลอดภัยด้วยประเภทข้อมูล
การใช้งาน Worker เบื้องต้น
-
การสร้าง Worker
สร้างอินสแตนซ์
Workerและรันสคริปต์ที่กำหนด โดยปกติ, สคริปต์จะถูกกำหนดไว้ในไฟล์แยกต่างหาก -
การแลกเปลี่ยนข้อความ
ส่งและรับข้อความระหว่างเธรดหลักและเธรด
Workerโดยใช้postMessageและonmessage
ตัวอย่าง: การใช้งาน Worker เบื้องต้น
- worker.ts: สคริปต์สำหรับ Worker
1// worker.ts
2self.onmessage = (event) => {
3 const data = event.data;
4 const result = data.num1 + data.num2;
5 self.postMessage(result); // Return the result to the main thread
6};- main.ts: สคริปต์สำหรับการใช้ Worker ในเธรดหลัก
1// main.ts
2const worker = new Worker(
3 new URL('./worker.ts', import.meta.url),
4 { type: 'module' }
5);
6
7worker.onmessage = (event) => {
8 console.log("Result from worker:", event.data); // Receive message from the worker
9};
10
11worker.postMessage({ num1: 10, num2: 20 }); // Send message to the worker
- ในตัวอย่างนี้,
worker.tsจะทำงานในเธรดแยก, คำนวณผลรวมของnum1และnum2, และส่งกลับมายังเธรดหลัก เธรดหลักจะรับผลลัพธ์และแสดงในคอนโซล - เมื่อคุณระบุ
type: 'module'สคริปต์ Worker จะถูกตีความว่าเป็น ES module ซึ่งทำให้คุณสามารถใช้importและexportได้ สิ่งนี้ช่วยให้คุณจัดการโครงสร้างโมดูลได้โดยไม่ต้องใช้importScripts()แบบดั้งเดิม
ข้อควรคำนึงเมื่อใช้ Workers ใน TypeScript
การเพิ่มการกำหนดประเภท
ใน TypeScript, กำหนดประเภทข้อมูลเพื่อรักษาความปลอดภัยในประเภทข้อมูลระหว่างการส่งและรับข้อความ
1// Define data types
2interface WorkerData {
3 num1: number;
4 num2: number;
5}
6
7interface WorkerResult {
8 result: number;
9}
10
11// worker.ts
12self.onmessage = (event: MessageEvent<WorkerData>) => {
13 const data = event.data;
14 const result = data.num1 + data.num2;
15 const message: WorkerResult = { result };
16 self.postMessage(message); // Send the result in a type-safe manner
17};
18
19// main.ts
20const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
21
22// Type the event from the worker
23worker.onmessage = (event: MessageEvent<WorkerResult>) => {
24 console.log("Result from worker:", event.data); // event.data is number
25};
26
27// Send typed data to the worker
28const message: WorkerData = { num1: 10, num2: 20 };
29worker.postMessage(message);- ด้วยการกำหนดพารามิเตอร์ประเภทใน
MessageEvent, คุณสามารถระบุประเภทของข้อมูลที่จะรับได้อย่างชัดเจน สิ่งนี้ช่วยให้การแลกเปลี่ยนข้อมูลเป็นไปอย่างปลอดภัยด้วยประเภทข้อมูล
การตั้งค่า Webpack หรือ Vite
เมื่อใช้ Worker ใน TypeScript อาจจำเป็นต้องใช้ bundlers เช่น Webpack หรือ Vite การใช้เครื่องมือเหล่านี้ช่วยให้สามารถจัดการ bundle สคริปต์ของ Worker ได้อย่างเหมาะสม และใช้งานได้จาก main thread
ตัวอย่างเช่น เมื่อใช้ Vite ให้ใช้ import.meta.url เพื่อนำเข้า Worker ได้อย่างถูกต้อง
1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });- สิ่งนี้ช่วยให้มั่นใจว่าสคริปต์
Workerที่ bundle แล้วถูกโหลดอย่างถูกต้อง ช่วยให้สามารถประมวลผลผ่านWorkerได้
ข้อพิจารณาเกี่ยวกับการส่งข้อความและการทำงานพร้อมกัน
-
การคัดลอกข้อมูล
เมื่อส่งและรับข้อความระหว่าง main thread และ
Workerthread ข้อมูลจะถูก คัดลอก เมื่อจัดการกับข้อมูลที่ซับซ้อน เช่น ออบเจ็กต์ จำเป็นต้องพิจารณาประสิทธิภาพในการทำงาน การแลกเปลี่ยนข้อมูลจำนวนมากบ่อยครั้งอาจทำให้ประสิทธิภาพลดลง -
อ็อบเจ็กต์ชนิด
Transferableวัตถุบางประเภท เช่น
ArrayBufferจะถูกเรียกว่าTransferableวัตถุTransferableสามารถส่งต่อไปยัง Worker ได้โดยไม่ต้องทำสำเนาในระหว่างการส่งข้อความ สิ่งนี้ช่วยหลีกเลี่ยงการเพิ่มภาระในการคัดลอกข้อมูล
1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3const buffer = new ArrayBuffer(1024);
4worker.postMessage(buffer, [buffer]); // Transfer ownership to the Worker
5
6console.log(buffer.byteLength); // 0 (ownership moved)
-
โดยการส่ง
[buffer]เป็นอาร์กิวเมนต์ตัวที่สองให้กับworker.postMessage()จะเป็นการโอนbufferไปให้ Worker แทนที่จะสำเนา -
หลังจากนั้น
bufferในเธรดหลักจะว่างเปล่า (byteLengthเป็น 0) และจะสามารถใช้งานได้โดย Worker เท่านั้น
การหยุดการทำงานของ Worker
Worker ควรถูกหยุดทำงานหลังการใช้งานเพื่อลดการใช้หน่วยความจำ คุณสามารถหยุดการทำงานของ Worker ได้โดยใช้เมธอด terminate
1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2// ...
3
4worker.terminate(); // Terminate the Worker
- โค้ดนี้จะยกเลิกการทำงานของ Worker โดยใช้เมธอด
terminate
การจัดการข้อผิดพลาดใน Worker
หากเกิดข้อผิดพลาดใน Worker คุณสามารถจัดการข้อผิดพลาดโดยใช้ event onerror
1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3worker.onerror = (error) => {
4 console.error("Error in Worker:", error.message);
5};- โค้ดนี้ใช้เหตุการณ์
onerrorเพื่อดักจับและจัดการข้อผิดพลาดที่เกิดขึ้นภายใน Worker
สรุป
การใช้ Worker ใน TypeScript ช่วยให้คุณสามารถดำเนินงานที่หนักในแบ็กกราวด์ได้ โดยยังคง main thread ทำงานได้อย่างราบรื่น ด้วยการใช้การกำหนดประเภท การแลกเปลี่ยนข้อความก็สามารถทำได้อย่างปลอดภัยและสอดคล้องกับประเภท ด้วยการใส่ใจในเรื่องการแลกเปลี่ยนข้อมูลและการจัดการ thread คุณสามารถปรับปรุงประสิทธิภาพและการทำงานพร้อมกันได้อย่างมีประสิทธิภาพ
คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย