مقدمه
همانطور که در درسهای ابتدایی اشاره شد، جاوااسکریپت در
مرورگر به صورت پیشفرض یک زبان تک-ریسمانی (single-threaded) است. این به این معنی است که تمام
کارها، از اجرای منطق جاوااسکریپت و دستکاری DOM گرفته تا واکنش به رویدادهای کاربر، همگی در یک
ریسمان اصلی به نام «ریسمان رابط کاربری» (UI thread) انجام میشوند.
این مدل تا زمانی که عملیاتها سریع باشند به خوبی کار میکند. اما اگر یک وظیفه سنگین و زمانبر
(مانند محاسبات پیچیده ریاضی، پردازش یک تصویر بزرگ، یا مرتبسازی یک آرایه بسیار حجیم) روی این
ریسمان اجرا شود، کل صفحه "قفل" یا "فریز" میشود. در این مدت، کاربر نمیتواند روی دکمهها کلیک
کند، اسکرول کند، یا هیچ تعامل دیگری با صفحه داشته باشد. این تجربه کاربری بسیار نامطلوبی ایجاد
میکند.
راه حل: اجرای کد در پسزمینه با Web Workers
Web Workers راهحل بومی مرورگرها برای اجرای واقعی چندریسمانی (multi-threading) در
جاوااسکریپت است. یک Worker به ما اجازه میدهد تا یک اسکریپت جاوااسکریپت را در یک ریسمان
پسزمینه، کاملاً مجزا از ریسمان اصلی UI، اجرا کنیم.
مزیت اصلی این کار این است که میتوانیم تمام وظایف سنگین و محاسباتی را به Workerها محول کنیم. با
این کار، ریسمان اصلی آزاد باقی میماند تا به سرعت به تعاملات کاربر پاسخ داده و رابط کاربری روان
و پاسخگو باقی بماند.
نحوه عملکرد و محدودیتهای Workerها
یک Worker در یک محیط ایزوله اجرا میشود که دارای ویژگیها و محدودیتهای خاص خود است:
- حوزه سراسری مجزا: یک Worker در یک حوزه سراسری متفاوت از شیء window صفحه اصلی
اجرا میشود. شیء سراسری در داخل یک Worker، معمولاً از طریق self قابل دسترسی است.
- عدم دسترسی به DOM: این مهمترین محدودیت یک Worker است. برای جلوگیری از مشکلات پیچیده
همزمانی، Workerها به هیچ وجه به اشیاء window و document دسترسی ندارند. این
یعنی شما نمیتوانید از داخل یک Worker مستقیماً DOM را دستکاری کنید.
- ارتباط از طریق پیامرسانی: تنها راه ارتباط بین ریسمان اصلی و یک Worker، از طریق ارسال
و دریافت پیام است. هر دو طرف از متد postMessage() برای ارسال
داده و از شنونده رویداد message برای دریافت آن استفاده میکنند.
- دسترسی به سایر APIها: با وجود عدم دسترسی به DOM، یک Worker به بسیاری از APIهای دیگر
وب مانند navigator، XMLHttpRequest، Fetch، WebSockets و
IndexedDB دسترسی دارد.
انواع Workerها
API مربوط به Workerها شامل چند نوع مختلف است که هر کدام برای کاربرد خاصی طراحی شدهاند و در
درسهای بعدی به تفصیل بررسی خواهند شد.
Dedicated Workers
این رایجترین نوع Worker است. یک `Dedicated Worker` توسط یک اسکریپت ایجاد شده و به صورت
«اختصاصی» تنها به همان اسکریپت تعلق دارد. ارتباط فقط بین آن اسکریپت و Worker برقرار است.
Shared Workers
یک `Shared Worker` میتواند توسط چندین زمینه مختلف (مانند چند تب، <iframe> یا حتی Worker
دیگر) به اشتراک گذاشته شود، به شرطی که همگی از یک مبدأ (origin) باشند. تمام این زمینهها
میتوانند با یک `Shared Worker` واحد ارتباط برقرار کنند.
Service Workers
این قدرتمندترین و پیچیدهترین نوع Worker است. یک `Service Worker` در واقع مثل یک پراکسی بین وب
اپلیکیشن، مرورگر و شبکه عمل میکند. این Worker حتی زمانی که صفحه مربوط به آن بسته است، میتواند
در پسزمینه فعال باشد. `Service Worker`ها اساس تکنولوژیهایی مانند اپلیکیشنهای وب پیشرونده
(PWA)، قابلیت کار آفلاین (از طریق کش کردن منابع)، اعلانهای فشاری (Push Notifications) و
همگامسازی داده در پسزمینه هستند.
در این درس با مفهوم کلی Web Workers به عنوان راه حلی برای مشکل تک-ریسمانی بودن
جاوااسکریپت و نقش آنها در جلوگیری از مسدود شدن رابط کاربری آشنا شدیم و انواع مختلف آنها را معرفی
کردیم. در درس بعدی، به سراغ اولین و رایجترین نوع، یعنی Dedicated Workers، خواهیم رفت و
به صورت عملی یاد میگیریم که چگونه یک Worker بسازیم، با آن ارتباط برقرار کنیم و یک وظیفه سنگین
را به آن محول کنیم.