مقدمه
در درس قبل با مفهوم کلی Workerها آشنا شدیم. Dedicated Worker یا «ورکر اختصاصی»، همانطور که از
نامش پیداست، یک ریسمان پسزمینه است که به صورت اختصاصی توسط یک اسکریپت واحد ایجاد شده و تنها با
همان اسکریپت میتواند ارتباط برقرار کند. این رایجترین و سادهترین نوع Worker است و برای زمانی
که میخواهید یک وظیفه (task) مشخص را از ریسمان اصلی جدا کنید، انتخاب ایدهآلی است.
ایجاد Worker و برقراری ارتباط
استفاده از یک Dedicated Worker نیازمند دو فایل جاوااسکریپت است: یکی اسکریپت اصلی شما (که در
صفحه HTML بارگذاری میشود) و دیگری، فایل اسکریپت مربوط به خود Worker که قرار است در پسزمینه
اجرا شود.
۱. اسکریپت اصلی (Main Script)
در اسکریپت اصلی، شما وظیفه ایجاد Worker و مدیریت ارتباط با آن را بر عهده دارید.
- ایجاد Worker: با استفاده از سازنده new Worker() و دادن آدرس فایل اسکریپت Worker، یک
نمونه جدید از آن میسازید: const myWorker = new Worker('worker.js';)
- ارسال پیام به Worker: برای ارسال داده به Worker، از متد myWorker.postMessage(data) استفاده میکنید.
- دریافت پیام از Worker: برای دریافت نتایج از Worker، یک شنونده برای رویداد
message روی شیء Worker ثبت میکنید: myWorker.onmessage = function(event) { ... }.
دادهی ارسال شده در event.data قرار دارد.
۲. اسکریپت ورکر (Worker Script)
فایل اسکریپت Worker در محیط ایزوله خود اجرا میشود و وظیفه انجام کار سنگین را دارد.
- دریافت پیام از اسکریپت اصلی: در داخل Worker، با ثبت یک شنونده برای رویداد
message روی شیء سراسری self، به پیامهای ارسالی از ریسمان اصلی گوش میدهید:
self.onmessage = function(event) { ... }.
- ارسال پیام به اسکریپت اصلی: پس از انجام محاسبات، Worker نتیجه را با استفاده از متد
سراسری postMessage(result) به ریسمان اصلی بازمیگرداند.
مثال عملی: یک محاسبه سنگین
بیایید این مفاهیم را با یک مثال واقعی بررسی کنیم. فرض کنید میخواهیم یک عدد بزرگ در دنباله
فیبوناچی را محاسبه کنیم. این یک عملیات بازگشتی و بسیار سنگین است که اگر در ریسمان اصلی اجرا شود،
قطعاً رابط کاربری را برای مدتی قفل خواهد کرد. ما این محاسبه را به یک Worker واگذار میکنیم.
JAVASCRIPT - a file named fib-worker.js
function fibonacci(n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
self.onmessage = (event) => {
console.log('Worker received number:', event.data);
const result = fibonacci(event.data);
self.postMessage(result);
};
این فایل fib-worker.js است. این اسکریپت منتظر دریافت یک پیام (که حاوی عدد مورد نظر است)
میماند، تابع سنگین fibonacci را اجرا کرده و نتیجه را به ریسمان اصلی بازمیگرداند.
JAVASCRIPT - a file named main.js
const numberInput = document.getElementById('fib-input');
const startBtn = document.getElementById('start-btn');
const resultDiv = document.getElementById('result');
const fibWorker = new Worker('fib-worker.js');
startBtn.addEventListener('click', () => {
resultDiv.textContent = 'Calculating...';
fibWorker.postMessage(Number(numberInput.value));
});
fibWorker.onmessage = (event) => {
resultDiv.textContent = 'Result: ' + event.data;
};
این کد مربوط به اسکریپت اصلی است. ابتدا یک نمونه از Worker میسازد. با کلیک روی دکمه، عدد را از
فیلد ورودی گرفته و به Worker ارسال میکند. سپس با ثبت شنونده onmessage، منتظر دریافت
نتیجه میماند و به محض دریافت، آن را در صفحه نمایش میدهد. در تمام مدت محاسبه، رابط کاربری
کاملاً روان و پاسخگو باقی میماند.
مدیریت خطا و پایان دادن به Worker
برای مدیریت خطاهایی که ممکن است در داخل Worker رخ دهد، میتوانید در اسکریپت اصلی به رویداد
error روی شیء Worker گوش دهید. همچنین، برای متوقف کردن اجباری یک Worker از ریسمان اصلی،
میتوانید متد worker.terminate() را فراخوانی کنید. این کار ریسمان
Worker را بلافاصله از بین میبرد.
JAVASCRIPT - in main.js
fibWorker.onerror = (event) => {
console.error('An error occurred in the worker!');
console.error(`Filename: ${event.filename}, Line: ${event.lineno}, Message: ${event.message}`);
resultDiv.textContent = 'An error occurred in calculation.';
};
در این درس به صورت عملی یاد گرفتیم که چگونه با استفاده از یک Dedicated Worker، وظایف سنگین را
به پسزمینه منتقل کرده و از پاسخگو بودن رابط کاربری اطمینان حاصل کنیم. این رایجترین الگوی
استفاده از Workerها است و یک ابزار کلیدی برای بهینهسازی عملکرد اپلیکیشنهای وب پیچیده محسوب
میشود. در درس بعدی، به سراغ «کار با Shared Workers» خواهیم رفت و یاد میگیریم که چگونه یک
Worker واحد میتواند بین چندین تب یا پنجره مختلف به اشتراک گذاشته شود.