Dark mode
worker_threads
worker_threads เป็นโมดูลในตัวของ Node.js ที่ช่วยให้สามารถรัน JavaScript ในเธรดแบบขนาน (parallel threads) ได้ เหมาะสำหรับงานที่ใช้ CPU หนักๆ เพื่อไม่ให้บล็อก Event Loop หลัก
import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
API | คำอธิบาย | ลักษณะ | คำอธิบายเพิ่มเติม |
---|---|---|---|
Worker | คลาสสำหรับสร้างและจัดการ Worker Thread | Class | ใช้สร้างเธรดใหม่เพื่อรันงานแบบขนาน |
isMainThread | ตรวจสอบว่าโค้ดกำลังรันในเธรดหลักหรือไม่ | Boolean | คืนค่า true ถ้าเป็นเธรดหลัก, false ถ้าเป็น Worker Thread |
parentPort | ช่องทางการสื่อสารกับเธรดหลัก | MessagePort | ใช้ใน Worker Thread เพื่อส่ง/รับข้อมูลจากเธรดหลัก |
workerData | ข้อมูลที่ส่งจากเธรดหลักไปยัง Worker | Any | ใช้ส่งข้อมูลเริ่มต้นให้ Worker Thread ไม่ต้องใช้ parentPort |
MessageChannel | ช่องทางการสื่อสารระหว่าง Worker Threads | Class | สร้างคู่ MessagePort สำหรับสื่อสารโดยตรงระหว่างเธรด |
MessagePort | ปลายทางสำหรับส่ง/รับข้อความระหว่างเธรด | Class | ใช้รับฟังและส่งข้อความผ่าน event 'message' |
threadId | ID ของเธรดปัจจุบัน | Integer | ค่าเฉพาะสำหรับแต่ละเธรด |
SHARE_ENV | ตัวแปรสำหรับแชร์ env ระหว่างเธรด | Symbol | ใช้กับ Worker constructor เพื่อแชร์ process.env กับ Worker Thread |
worker.resourceLimits | ตรวจสอบขีดจำกัดทรัพยากรของ Worker | Object | แสดงค่าขีดจำกัดหน่วยความจำและ CPU |
worker.performance | ข้อมูลประสิทธิภาพของ Worker | Object | มีเมธอดสำหรับวัดประสิทธิภาพการทำงานของ Worker Thread |
ตัวอย่าง
การสร้าง Worker เบื้องต้น
js
// main.js (เธรดหลัก)
import { isMainThread, Worker } from "worker_threads";
if (isMainThread) {
// สร้าง Worker Thread
const worker = new Worker("./worker.js", {
workerData: { initialData: "Hello from Main Thread" },
});
// รับข้อมูลจาก Worker
worker.on("message", (msg) => {
console.log("จาก Worker:", msg);
});
// จัดการเมื่อ Worker ส่งข้อผิดพลาด
worker.on("error", (err) => {
console.error("Worker เกิดข้อผิดพลาด:", err);
});
// จัดการเมื่อ Worker ปิดตัวเอง
worker.on("exit", (code) => {
console.log("Worker ปิดตัวเองด้วยรหัส:", code);
});
}
// worker.js (Worker Thread)
import { parentPort, workerData } from "worker_threads";
// รับข้อมูลเริ่มต้นจากเธรดหลัก
console.log("ข้อมูลเริ่มต้น:", workerData.initialData);
// ส่งข้อมูลกลับไปยังเธรดหลัก
parentPort.postMessage({ result: "Hello from Worker Thread" });
การส่งข้อมูลระหว่าง threads
js
// main.js
import { Worker } from "worker_threads";
const worker = new Worker("./worker.js");
// ส่งข้อมูลไปยัง Worker
worker.postMessage({ task: "process_data", data: [1, 2, 3, 4, 5] });
// worker.js
import { parentPort } from "worker_threads";
parentPort.on("message", (msg) => {
if (msg.task === "process_data") {
const result = msg.data.map(x => x * 2);
parentPort.postMessage({ result });
}
});
การใช้ MessageChannel
js
import { MessageChannel, Worker } from "worker_threads";
const { port1, port2 } = new MessageChannel();
const worker = new Worker("./worker.js", {
workerData: { port: port2 },
transferList: [port2],
});
port1.on("message", (msg) => {
console.log("ได้รับจาก Worker:", msg);
});
port1.postMessage("Hello from Main Thread");
การจัดการ Worker Pool
js
import { Worker } from "worker_threads";
class WorkerPool {
constructor(numThreads, workerPath) {
this.workers = [];
for (let i = 0; i < numThreads; i++) {
const worker = new Worker(workerPath);
this.workers.push(worker);
}
this.taskQueue = [];
}
execute(task) {
return new Promise((resolve) => {
const worker = this.workers.pop();
if (worker) {
worker.once("message", (result) => {
this.workers.push(worker);
resolve(result);
});
worker.postMessage(task);
} else {
this.taskQueue.push({ task, resolve });
}
});
}
}
// ใช้งาน
const pool = new WorkerPool(4, "./worker.js");
pool.execute({ data: "example" }).then(console.log);