آشنایی با Web Worker ها و SSE

09 خرداد 1398
درسنامه درس 38 از سری آموزش صفر تا صد HTML
HTML-web-worker

به قسمت آخر از سری آموزشی صفر تا صد HTML5 خوش آمدید! به شما تبریک می گوییم که تا اینجای کار با ما همراه بوده اید! بیایید بدون مقدمه به سراغ مطالب قسمت آخر برویم.

Web Worker چیست؟

Web Worker (در لغت به معنی کارگر یا کارگذار وب) کدهای جاوا اسکریپتی هستند که در پس زمینه در حال اجرا شدن هستند، بدون اینکه کارایی و سرعت وب سایت ما را دچار مشکل کنند. در واقع زمانی که اسکریپت های ما در صفحه ی HTML اجرا می شوند، تا پایان اجرای اسکریپت، صفحه متوقف می شود و واکنش نشان نمی دهد.

در طرف مقابل web worker ها هستند که در پس زمینه اجرا می شوند، از کدهای دیگر مستقل هستند و روی عملکرد و سرعت سایت هیچ تاثیری نمی گذارند. بنابراین زمانی که web worker ها در حال کار هستند، کاربر می تواند هر کاری دوست دارد بکند (کلیک کردن، select کردن و ....).

وضعیت پشتیبانی از این ویژگی در مرورگر های مطرح دنیا به این شرح است:

مرورگر کروم فایرفاکس اپرا سافاری اینترنت اکسپلورر یا Edge
نسخه 4.0 3.5 11.5 4.0 10.0

در مثال زیر یک web worker ساده ایجاد کرده ایم که ثانیه ها را در پس زمینه می شمارد:

<!DOCTYPE html>
<html>
<body>

<p>Count numbers: <output id="result"></output></p>
<button dir='rtl' onclick="startWorker()">شروع به کار web worker</button> 
<button dir='rtl' onclick="stopWorker()">پایان کار web worker</button>

<p dir='rtl'><strong>هشدار:</strong>Internet Explorer 9 و نسخه های قدیمی تر آن از قابلیت web worker ها پشتیبانی نمی کنند.</p>

<script>
var w;

function startWorker() {
  if(typeof(Worker) !== "undefined") {
    if(typeof(w) == "undefined") {
      w = new Worker("demo_workers.js");
    }
    w.onmessage = function(event) {
      document.getElementById("result").innerHTML = event.data;
    };
  } else {
    document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Workers...";
  }
}

function stopWorker() { 
  w.terminate();
  w = undefined;
}
</script>

</body>
</html>

مشاهده ی خروجی در JSBin

البته همیشه بهتر است قبل از کار با web worker ها از پشتیبانی مرورگر کاربر مطمئن شوید:

if (typeof(Worker) !== "undefined") {
  // Web worker کار می کند!
  // کد های مورد نظرتان را اینجا بنویسید.
} else {
  // متاسفانه Web worker برای شما کار نمی کند
}

ساخت یک web worker

بیایید یک web worker در یک فایل جاوا اسکریپت (به صورت external) بسازیم. اسکریپت زیر یک شمارنده است و در فایل demo_workers.js قرار داده شده است:

var i = 0;

function timedCount() {
  i = i + 1;
  postMessage(i);
  setTimeout("timedCount()",500);
}

timedCount();

قسمت مهم این کد ()postMessage است که کارش ارسال یک پیام به HTML است.

نکته: این تنها یک مثال برای آشنایی شماست. در واقعیت معمولا برای چنین اسکریپت ساده ای از web worker ها استفاده نمی شود بلکه در مواقعی مورد استفاده قرار می گیرند که اسکریپت، CPU و قدرت پردازشی زیادی اشغال کند.

حالا که فایل اسکریپت مورد نظرمان را داریم باید آن را از صفحه ی HTML صدا بزنیم. کد زیر چک می کند تا ببیند آیا در حال حاضر worker ای وجود دارد یا نه. اگر هیچ worker ای وجود نداشته باشد، یک شیء worker جدید می سازد و کد های فایل demo_workers.js را اجرا می کند:

if (typeof(w) == "undefined") {
  w = new Worker("demo_workers.js");
}

حالا می توانیم از طریق web worker پیام هایی را ارسال و دریافت کنیم. در اینجا یک event listener از نوع رویداد onmessage را به worker خود اضافه می کنیم:

w.onmessage = function(event){
  document.getElementById("result").innerHTML = event.data;
};

زمانی که worker ما پیامی را ارسال کند، event listener اجرا خواهد شد. همچنین داده هایی که از worker ارسال می شوند در event.data ذخیره خواهند شد.

البته باید حواسمان به نکته ای دیگر نیز باشد؛ زمانی که شیء web worker ساخته می شود، حتی پس از پایان اجرای اسکریپت، در حال گوش دادن (listen) به پیام های جدید است مگر اینکه آن را از بین ببریم. برای از بین بردن web worker ها و رها کردن منابع سیستمی کاربر از دستور زیر استفاده کنید:

w.terminate();

اگر پس از حذف worker، متغیر اش را برابر با undefined کنید می توانید دوباره از کد قبلی استفاده کنید:

w = undefined;

حالا می توانیم کاملا متوجه کد زیر شویم:

<!DOCTYPE html>
<html>
<body>

<p>Count numbers: <output id="result"></output></p>
<button dir='rtl' onclick="startWorker()">شروع به کار web worker</button> 
<button dir='rtl' onclick="stopWorker()">پایان کار web worker</button>

<p dir='rtl'><strong>هشدار:</strong>Internet Explorer 9 و نسخه های قدیمی تر آن از قابلیت web worker ها پشتیبانی نمی کنند.</p>

<script>
var w;

function startWorker() {
  if(typeof(Worker) !== "undefined") {
    if(typeof(w) == "undefined") {
      w = new Worker("demo_workers.js");
    }
    w.onmessage = function(event) {
      document.getElementById("result").innerHTML = event.data;
    };
  } else {
    document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Workers...";
  }
}

function stopWorker() { 
  w.terminate();
  w = undefined;
}
</script>

</body>
</html>

مشاهده ی خروجی در JSBin

نکته: از آنجایی که web worker ها در فایل های خارجی (External) هستند، به اشیاء جاوا اسکریپت زیر دسترسی ندارند:

  • window object
  • document object
  • parent object

Server-Sent Event چیست؟

Server-Sent Event یا به طور مخفف SSE (در لغت به معنی «رویداد های ارسالی از سمت سرور») به صفحات وب اجازه می دهند که به طور اتوماتیک و خودکار از سرور بروزرسانی دریافت کنند.

این قابلیت از قبل هم در HTML مهیا بود اما خودکار نبود و صفحه باید از سرور سوال می کرد که آیا بروزرسانی جدیدی وجود دارد یا نه. مثال های این نوع رویداد ها را در آپدیت های Facebook و Twitter، سایت های اعلام نرخ بورس (که به شکل لحظه ای بروزرسانی می شوند)، فید های اخبار و ... دیده اید.

وضعیت پشتیبانی از این ویژگی در مرورگر ها به این شرح است:

مرورگر کروم فایرفاکس اپرا سافاری اینترنت اکسپلورر یا Edge
نسخه 6.0 6.0 11.5 5.0 پشتیبانی نمی‌کند.

برای دریافت اعلان های SSE نیاز به شیء EventSource داریم. به مثال زیر توجه کنید:

<!DOCTYPE html>
<html>
<body>

<h1>Getting server updates</h1>
<div id="result"></div>

<script>
if(typeof(EventSource) !== "undefined") {
  var source = new EventSource("demo_sse.php");
  source.onmessage = function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
  };
} else {
  document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>

</body>
</html>

مشاهده ی خروجی

در کد بالا ابتدا یک شیء EventSource ساخته ایم و آدرس URL صفحه ای را به آن داده ایم که اعلان ها یا بروزرسانی ها را می فرستد (در این مثال -> demo_sse.php). هر بار که بروزرسانی ای دریافت شود، رویداد onmessage اجرا خواهد شد و زمانی که این رویداد اجرا شود داده های ارسالی را گرفته و در عنصری با id برابر با "id="result قرار می دهد. بقیه ی قسمت های کد برای چک کردن پشتیبانی مرورگر از این قابلیت بودند. شکل ساده و جدا شده ی آن به این صورت است:

if(typeof(EventSource) !== "undefined") {
  // مرورگر از Server-sent event پشتیبانی می کند
  // کد مورد نظر را اینجا بنویسید
} else {
  // متاسفانه مرورگر شما از Server-sent event پشتیبانی نمی کند.
}

اما ما هنوز کد های درون demo_sse.php را ندیده ایم. برای اینکه مثال بالا کار کند باید سروری داشته باشید که قابلیت ارسال بروزرسانی را داشته باشد (مانند PHP یا ASP). کدنویسی سمت سرور برای این مثال ساده است؛ باید مقدار Content-Type در header را روی "text/event-stream" تنظیم کنید و سپس می توانید بروزرسانی هایتان را به صفحه ی وب ارسال کنید. محتوای فایل به این شکل است:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>

اگر بخواهیم آن را در ASP بنویسیم می گوییم:

<%
Response.ContentType = "text/event-stream"
Response.Expires = -1
Response.Write("data: The server time is: " & now())
Response.Flush()
%>

همانطور که گفتیم ابتدا Content-Type را روی text/event-stream تنظیم کرده ایم. سپس گفته ایم که صفحه نباید چیزی را cache کند (اگر cache شود دیگر بروزرسانی نمایش داده نخواهد شد). در مرحله ی بعد داده های مورد نظر را برای ارسال آماده کرده ایم (همیشه با " :data" شروع شود) و در آخر داده را با دستور Flush به سمت صفحه می فرستیم تا نمایش داده شود.

ما در مثال بالا از رویداد onmessage استفاده کرده ایم اما رویداد های دیگری نیز وجود دارد:

  • onopen: زمانی که اتصال با سرور برقرار می شود.
  • onmessage: زمانی که پیامی دریافت می شود.
  • onerror: زمانی که خطایی رخ می دهد.

امیدوارم از این قسمت لذت برده باشید. این قسمت، قسمت آخر از این سری آموزشی بود اما در آینده ممکن است مقالات مستقلی در اختیار شما عزیزان قرار دهیم. شما با گذراندن این دوره با تمام مسائل اصلی و جزئی HTML آشنا شده اید و می توانید یک صفحه ی وب را پایه ریزی کنید. تا دوره ای دیگر بدرود!

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش صفر تا صد HTML توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (5 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

mobin
22 اردیبهشت 1401
عالی... دمتون گرم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
22 اردیبهشت 1401
دم خودتون گرم :)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

EYRES
24 مرداد 1399
جامع و بسیار مفید آرزوی موفقیت های فراوان برای عوامل سایت رو دارم .

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

amir abedin
24 مرداد 1399
حاجی واااقعا دمتون خیلی مشتی...همه چیز کامل با جزئیات و کاربردی

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

samaneh
18 آذر 1398
mersi az amozeshetoon

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

فاطمه
20 مرداد 1398
عالی بود

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
21 مرداد 1398
سلام دوست عزیز خوشحالم که مقاله بهتون کمک کرده.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.