مقدمه
در درس قبل با Web Sockets و قدرت آن برای ارتباطات دوطرفه آشنا شدیم. اما در بسیاری از
سناریوها، ما فقط به یک کانال ارتباطی یکطرفه از سرور به کلاینت نیاز داریم. برای
مثال، یک وبسایت خبری که میخواهد آخرین اخبار را به کاربران نمایش دهد، یا یک داشبورد که قیمت
لحظهای سهام را نشان میدهد. در این موارد، کلاینت عمدتاً یک شنونده است و نیازی به ارسال مداوم
داده به سرور ندارد.
برای این نوع کاربردها، یک تکنولوژی سادهتر و سبکتر به نام Server-Sent Events (SSE) یا
«رویدادهای ارسالشده از سرور» وجود دارد. SSE به یک صفحه وب اجازه میدهد تا پس از برقراری یک
ارتباط اولیه، به صورت خودکار بهروزرسانیها را از سرور دریافت کند. این ارتباط روی پروتکل
استاندارد HTTP برقرار میشود و در سمت کلاینت، با استفاده از رابط EventSource پیادهسازی
میشود.
EventSource در مقابل WebSocket
انتخاب بین SSE و WebSocket بستگی به نیاز پروژه شما دارد. درک تفاوتهای کلیدی آنها به این
انتخاب کمک میکند:
- جهت ارتباط: SSE کاملاً یکطرفه (از سرور به کلاینت) است. WebSocket دوطرفه است و هر
دو طرف میتوانند هر زمان که بخواهند پیام ارسال کنند.
- پروتکل: SSE روی HTTP/HTTPS استاندارد کار میکند و به زیرساخت خاصی نیاز ندارد.
WebSocket از پروتکل ws:// یا wss:// استفاده میکند که نیازمند پشتیبانی در سطح سرور
است.
- نوع داده: SSE فقط برای ارسال متن با انکودینگ UTF-8 طراحی شده است. WebSocket هم
از متن و هم از دادههای باینری خام پشتیبانی میکند.
- اتصال مجدد خودکار: EventSource به صورت داخلی قابلیت اتصال مجدد خودکار در صورت قطع
شدن ارتباط را دارد. در WebSocket، این منطق باید به صورت دستی پیادهسازی شود.
- پیچیدگی: SSE به دلیل سادگی و استفاده از HTTP، معمولاً پیادهسازی آسانتری هم در سمت
کلاینت و هم در سمت سرور دارد.
نتیجهگیری: اگر فقط نیاز به ارسال داده از سرور به کلاینت دارید (مانند سیستم نوتیفیکیشن یا
فید خبری)، SSE انتخاب بهینهتر و سادهتری است. اگر به یک کانال ارتباطی کاملاً دوطرفه (مانند یک
اپلیکیشن چت) نیاز دارید، WebSocket تنها گزینه است.
پیادهسازی در سمت کلاینت با EventSource
کار با SSE در سمت کلاینت بسیار ساده است. کافیست یک نمونه جدید از EventSource با آدرس URL
اندپوینتی که دادهها را ارسال میکند، بسازید. سپس با استفاده از شنوندگان رویداد، پیامها را
دریافت میکنید.
رویدادهای اصلی
- open: زمانی که اتصال با موفقیت برقرار میشود، اجرا میشود.
- message: این شنونده پیشفرض است و برای هر پیامی که از سرور میآید و نام رویداد مشخصی
ندارد، اجرا میشود. دادهی پیام در پراپرتی event.data قرار دارد.
- error: در صورت بروز خطا در اتصال، اجرا میشود. پس از این رویداد، مرورگر به صورت
خودکار تلاش میکند تا دوباره متصل شود.
- رویدادهای نامگذاری شده: سرور میتواند پیامهایی با نام رویداد سفارشی ارسال کند (مثلاً
event: user-update). در این صورت، ما میتوانیم با eventSource.addEventListener('user-update', ...) به طور خاص به
آن رویداد گوش دهیم.
JAVASCRIPT
const eventSource = new EventSource('/sse-endpoint');
eventSource.onopen = (event) => {
console.log('Connection to server established.');
};
eventSource.onmessage = (event) => {
console.log('Generic message received:', event.data);
};
eventSource.addEventListener('user-update', (event) => {
const userData = JSON.parse(event.data);
console.log('Received a user update:', userData);
});
eventSource.onerror = (event) => {
console.error('EventSource failed:', event);
};
این کد یک اتصال EventSource برقرار کرده و به رویدادهای مختلف آن گوش میدهد. مشاهده میکنید که
یک شنونده برای پیامهای عمومی (onmessage) و یک شنونده اختصاصی برای پیامهای با نام
user-update ثبت شده است.
فرمت داده در سمت سرور (نگاه کلی)
برای تکمیل درک شما، خوب است بدانید که سرور چگونه دادهها را ارسال میکند. سرور باید هدر
Content-Type را برابر با text/event-stream تنظیم کند و سپس پیامها را در یک فرمت متنی ساده
ارسال کند. هر پیام با data: شروع شده و با دو کاراکتر خط جدید (\n\n) از پیام بعدی جدا میشود.
SERVER-SIDE TEXT STREAM
data: This is the first message.
event: user-update
data: {"id": 123, "status": "online"}
: this is a comment
data: This is another message.
همانطور که میبینید، سرور با استفاده از پیشوند event: میتواند نام یک رویداد سفارشی را
مشخص کند که در کلاینت با addEventListener قابل دریافت است.
در این درس با EventSource API به عنوان یک روش ساده و کارآمد برای دریافت بهروزرسانیهای
زنده از سرور آشنا شدیم. این تکنولوژی برای اطلاعرسانیهای یکطرفه، جایگزین بسیار خوبی برای
Web Sockets است. با این درس، فصل «درخواستهای شبکه و منابع Remote» به پایان میرسد. ما در
این فصل از Fetch API و CORS گرفته تا Web Sockets و Server-Sent
Events، با طیف وسیعی از ابزارهای مدرن برای ارتباط با سرورها آشنا شدیم. در فصل بعدی، به
سراغ یکی از مهمترین جنبههای ساخت وب اپلیکیشنهای پیشرفته، یعنی «ذخیرهسازی دادهها در سمت
کاربر» خواهیم رفت.