الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
How To Make It

اعمل نظام إشعارات لحظية بـ SSE في Node.js بدون WebSocket

متوسط18 يوليو 20265 دقائق قراءة
اعمل نظام إشعارات لحظية بـ SSE في Node.js بدون WebSocket

المستوى: متوسط — الشرح يبدأ من الصفر بمثال بسيط، لكنه يفترض إنك تعرف أساسيات JavaScript و HTTP وشغّلت سيرفر Node.js قبل كده.

هتطلع من المقال ده وانت قادر تبعت إشعار للمتصفح في نفس اللحظة اللي بيحصل فيها الحدث، من غير ما المستخدم يعمل refresh، ومن غير ما تركّب WebSocket ولا مكتبة تقيلة. الأداة اسمها Server-Sent Events، وهنبنيها في أقل من 40 سطر.

المشكلة باختصار

عندك dashboard بيعرض طلبات جديدة أو تنبيهات. الطريقة الشائعة إن المتصفح يسأل السيرفر كل شوية: "في جديد؟" (اسمها polling). المشكلة إن أغلب الأسئلة دي بترجع فاضية.

لو عندك 2000 مستخدم متصلين، و polling كل 3 ثواني، ده حوالي 667 طلب في الثانية معظمها بيرد "لا يوجد جديد". هدر في السيرفر، وتأخير في الإشعار وسطه ثانية ونص. SSE بيقلب المعادلة: السيرفر هو اللي بيدفع، والمتصفح بيستنى بهدوء.

يعني إيه SSE؟ (بمثال الأول)

تخيّل محطة راديو. انت بتفتح المحطة مرة واحدة، وبعدها بتفضل قاعد تستقبل كل ما يذيعوه، أول بأول، من غير ما تتصل بيهم كل دقيقة تسأل "في أغنية جديدة؟". انت مجرد مستمع، والبث بيجيلك في اتجاه واحد.

SSE بالظبط كده. المتصفح بيفتح "قناة" واحدة للسيرفر وبيسيبها مفتوحة. السيرفر يفضّل يبعت رسائل على القناة دي كل ما يحصل حدث، والمتصفح يستقبلها لحظيًا.

علميًا: الـ Server-Sent Events معيار في مواصفة HTML، بيشتغل فوق اتصال HTTP عادي واحد يفضل مفتوح. السيرفر بيبعت الرد بنوع text/event-stream، وكل رسالة بتكون سطر يبدأ بـ data: وينتهي بسطرين فاضيين. المتصفح بيقرأها عبر كائن جاهز اسمه EventSource، وأهم ميزة إنه بيعيد الاتصال تلقائيًا لو الشبكة قطعت.

الخطوات: ابنِ نظام الإشعارات في Node.js

1. جهّز المشروع. ثبّت Express، هيسهّل التوجيه بس المبدأ نفسه شغّال بـ http الخام.

Bash
mkdir sse-demo && cd sse-demo
npm init -y
npm install express

النتيجة المتوقّعة: مجلد فيه node_modules و package.json.

2. افتح نقطة البث /events. دي اللي المتصفح هيتصل بيها ويسيبها مفتوحة. لاحظ الهيدرات: text/event-stream عشان المتصفح يفهم إنه بث، و X-Accel-Buffering: no عشان nginx ما يخزّنش الرسائل ويأخّرها.

JavaScript
const express = require("express");
const app = express();
const clients = new Set();

app.get("/events", (req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "X-Accel-Buffering": "no"
  });
  res.write("retry: 3000\n\n"); // اطلب من المتصفح ينتظر 3 ثواني قبل إعادة الاتصال
  clients.add(res);
  req.on("close", () => clients.delete(res)); // نظّف لما يقفل
});

النتيجة المتوقّعة: كل متصفح بيفتح /events بيتسجّل في clients ويفضل مفتوح.

3. اعمل دالة بث لكل المتصلين. كل رسالة لازم تنتهي بسطرين فاضيين \n\n، ده شرط في البروتوكول.

JavaScript
function broadcast(event) {
  const payload = `data: ${JSON.stringify(event)}\n\n`;
  for (const res of clients) res.write(payload);
}

4. اربط حدث حقيقي بالبث. مثلًا نقطة يستدعيها باقي النظام لما يوصل طلب جديد.

JavaScript
app.post("/notify", express.json(), (req, res) => {
  broadcast(req.body);
  res.json({ delivered: clients.size });
});

app.listen(3000, () => console.log("SSE شغّال على http://localhost:3000"));

النتيجة المتوقّعة: أي POST على /notify بيوصل فورًا لكل متصفح مفتوح.

5. استقبل في المتصفح بـ EventSource. سطرين وخلاص، والمتصفح بيتكفّل بإعادة الاتصال.

HTML
<script>
  const es = new EventSource("/events");
  es.onmessage = (e) => {
    const data = JSON.parse(e.data);
    console.log("إشعار جديد:", data);
  };
  es.onerror = () => console.log("انقطع الاتصال، المتصفح بيعيد المحاولة تلقائيًا");
</script>

6. ضيف نبضة (heartbeat) كل 15 ثانية. بعض الـ proxies بتقفل الاتصال الساكت. سطر تعليق يبدأ بنقطتين رأسيتين بيحافظ على الاتصال حي من غير ما يظهر للمستخدم.

JavaScript
setInterval(() => {
  for (const res of clients) res.write(": ping\n\n");
}, 15000);

التحقق من أنه يعمل

شغّل السيرفر، افتح الصفحة في المتصفح، وبعدين من الطرفية:

Bash
curl -X POST http://localhost:3000/notify \
  -H "Content-Type: application/json" \
  -d '{"title":"طلب جديد","id":1042}'

المفروض تشوف السطر إشعار جديد: {title: "طلب جديد", id: 1042} يظهر في الـ console فورًا، والرد يقول {"delivered":1}. جرّب اقفل السيرفر وشغّله تاني، هتلاقي المتصفح بيعيد الاتصال لوحده خلال 3 ثواني من غير ما تلمس حاجة.

SSE مقابل Polling مقابل WebSocket

مفيش أداة "أفضل" مطلقًا، فيه أداة مناسبة للحالة. الجدول ده بيوضح المقايضة:

المعيارPollingSSEWebSocket
الاتجاهذهاب وإيابمن السيرفر فقطاتجاهين كامل
التأخيرثوانٍلحظيلحظي
إعادة الاتصالغير موجودةتلقائية مدمجةتكتبها بنفسك
التعقيدبسيطبسيطأعلى + بنية تحتية
الأنسب لـتحديثات نادرةإشعارات، feeds، تقدّمشات، ألعاب

الـ trade-off هنا: بتكسب البساطة وإعادة الاتصال المجانية والاشتغال فوق HTTP عادي. بتخسر إن الاتصال في اتجاه واحد فقط (لو المستخدم عايز يبعت بيانات لحظية، هيعمل POST عادي أو تروح لـ WebSocket)، وإن الرسائل نصية UTF-8 مش ثنائية.

الافتراض المهم: على HTTP/1.1 المتصفح بيسمح بـ 6 اتصالات فقط لكل دومين. يعني 6 تابات مفتوحة تستهلك الحصة كلها ويتعطّل باقي طلباتك. الحل: شغّل على HTTP/2 (بيرفع الحد لحوالي 100 اتصال متزامن) أو استخدم دومين فرعي منفصل للبث.

متى لا تستخدم SSE

  • لو محتاج اتجاهين بزمن منخفض جدًا زي الشات أو الألعاب الجماعية، استخدم WebSocket.
  • لو بتبعت بيانات ثنائية (صور، ملفات)، SSE نصي فقط، روح لـ WebSocket.
  • لو التحديث بيحصل مرة في الساعة، الاتصال المفتوح رفاهية بلا داعي، polling بسيط أوفر.
  • لو هتستضيف على منصة serverless بتقفل الاتصالات الطويلة بعد ثواني، SSE مش هيثبت.

الخطوة التالية

انسخ الكود اللي فوق، شغّله محليًا، وابعت أول POST على /notify. لو الإشعار ظهر لحظيًا في الـ console، انت خلّصت النواة. بعد كده اربط broadcast() بأي حدث حقيقي عندك (طلب جديد، دفع، تنبيه) وحط /events خلف HTTP/2 قبل الإنتاج.

المصادر

  • مواصفة Server-Sent Events في معيار HTML — WHATWG HTML Standard
  • واجهة EventSource وطريقة إعادة الاتصال التلقائية — MDN Web Docs: EventSource
  • استخدام أحداث السيرفر (تنسيق الرسائل والحقول) — MDN: Using server-sent events
  • حد الاتصالات المتزامنة لكل مضيف على HTTP/1.1 — MDN: HTTP/1.x connection management

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة