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 และ
Worker
thread ข้อมูลจะถูก คัดลอก เมื่อจัดการกับข้อมูลที่ซับซ้อน เช่น ออบเจ็กต์ จำเป็นต้องพิจารณาประสิทธิภาพในการทำงาน การแลกเปลี่ยนข้อมูลจำนวนมากบ่อยครั้งอาจทำให้ประสิทธิภาพลดลง -
อ็อบเจ็กต์ชนิด
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 ด้วย