المقدمة
في عالم تطوير الويب، غالبًا بنحتاج ننقل بيانات أو نرسل رسائل بين تبويبات المتصفح المختلفة. على سبيل المثال، لو عندك تطبيق ويب مفتوح في أكثر من تبويب، وعايز التحديثات اللي تحصل في تبويب معين تنعكس على باقي التبويبات تلقائيًا، فأنت محتاج تستخدم الـ Broadcast Channel API، اللي بيسمحلك تعمل تواصل سهل وفعال بين التبويبات المختلفة لنفس المتصفح طالما كلها مفتوحة على نفس الصفحة أو صفحات مختلفة على نفس الـ domain حتى لو كانت مفتوحة على نوافذ مختلفة ولكن بشرط تكون لنفس المتصفح.
ليه محتاج تبعت بيانات بين التبويبات المختلفة ؟
لنفترض أننا محتاجين نزور أحد مواقع بيع الكتب ونتصفح الموقع بحثا عن مجموعة من الكتب المفيدة بالنسبة لنا عشان نشتريهم مثلا، فبدأنا رحلتنا من الصفحة الرئيسية للموقع وقابلنا كتاب بيتكلم عن JavaScript ففتحناه في علامة تبويب جديدة عشان نقدر نكمل تصفح في الصفحة الرئيسية ونبقى نشوف تفاصيل الكتاب بعدين (يمكن نلاقى كتب تانية فنشتريها بالمرة)، واستمرينا في التصفح لغاية ما لقينا كتاب تاني بيتكلم عن CSS وكالمعتاد فتحناه في علامة تبويب جديدة.
بعدها قررنا نزور علامات التبويب اللى فتحناها عشان نشوف تفاصيل كل كتاب منهم، وبالفعل الكتاب الأول نال اعجابنا وضيفناه لسلة المشتريات، ولاحظنا ظهور رقم 1 أعلى أيقونة سلة المشتريات للتعبير عن وجود منتج واحد بالسلة، بعدها فتحنا علامة التبويت التانية عشان نشوف الكتاب التاني وهنا لاحظنا إن الرقم 1 مش موجود لأن علامة التبويب دى مش عندها أى علم بأن في كتاب تم إضافته للسلة، ودا سبب لنا نوع من القلق عن إذا كان الكتاب الأول انضاف فعلا ولا لا، فرجعنا نبص عليه ولقيناه موجود فى السلة فعلا.
واستمرينا في رحلتنا بإضافة الكتاب التاني إلى السلة، وجات لحظة شراء الكتب اللى احتاجت مننا تسجيل الدخول للموقع، وبعد عملية تسجيل الدخول لاحظنا إن الصفحة اتعرفت علينا وبتعرض لنا اسم المستخدم في الـ navbar ولكن باقي الصفحات لسا مجالهاش خبر بأننا سجلنا دخول في الموقع فاضطرينا نعمل لهم ريفريش عشان يتحدثو بحيث ميحصلش اى مشكلة غير متوقعة، وبعدها تمت عملية الشراء بنجاح رغم إن بعض الصفحات لازالت مقتنعة إننا لسا مشتريناش الكتب، بل بعدها لما عملنا تسجيل خروج من الموقع لاحظنا إن بعض الصفحات لازالت بتعرض بيانات المستخدم!
التجربة دى غير لطيفة لبعض المستخدمين وممكن تخلى المستخدم يبعت Request من علامة تبويب بشراء منتجات هو حذفها أصلاً من علامة تبويب تانية، بس وقتها هو مش هيكون فاهم ليه الموقع بيقول له إن مفيش منتجات في السلة رغم إنه شايف الموقع بيعرض المنتجات قدامه، ومش هيفهم ليه الصفحة بتطلب تسجيل دخول رغم إنه سجل بالفعل ولكن من صفحة تانية، فعشان تحذف العبء دا من على دماغ المستخدم وتوفر له تجربة أفضل خلال رحلته أنت محتاج تخلى كل علامات التبويب متوافقين مع بعض وبيتحدثو باستمرار لو حصل تغيير بيستدعى دا ولكن في علامة تبويب مختلفة.
ودا بنقدر ننفذه من خلال الـ Broadcast Channel API اللى بيسمح لنا بارسال واستقبال البيانات بين علامات التبويب المختلفة.
طريقة استخدام الـ Broadcast Channel API
عملية التواصل بين علامات التبويب المختلفة محتاجة مننا 3 خطوات فرعية
- الخطوة الأولى هي إنشاء قناة للتواصل
- الخطوة التانية هى التجهيز لاستقبال الرسائل
- أما الخطوة التالتة والأخيرة هي ارسال البيانات على هيئة رسائل
الخطوة الأولى: إنشاء قناة للتواصل
يمكن إنشاء قناة للتواصل بين علامات التبويب المختلفة عن طريق الـ constructor الخاص بالـ BroadcastChannel وبواسطة الـ new keyword، كالمثال التالي:

بحيث my-channel هو اسم القناة ويمكن استبداله بأى اسم مناسب للهدف اللى تم إنشاء القناة من أجله، مثلا cart-channel أو auth-channel أو غيرهم.
الخطوة الثانية: التجهيز لاستقبال الرسائل
يمكن التجهيز لاستقبال الرسائل عن طريق إسناد function للـ onmessage property الخاصة بالـ channel اللى انشأناها، كالمثال التالي:

بحيث الـ function دى هى اللى هتـ run عند استقبال أي رسالة من علامات التبويب الأخرى وتستقبل parameter للـ event الخاصة بالرسالة دى (مش لازم تسميه event)، ونقدر من خلال الـ parameter دا نعرف تفاصيل أكتر عن الرسالة اللى استقبلناها.
الخطوة الثالثة والأخيرة: إرسال البيانات على هيئة رسائل
نقدر نبعت رسالة من علامة تبويب معينة إلى باقي التبويبات عن طريق method خاصة بالـ channel اسمها postMessage، كالمثال التالي:

بحيث الـ postMessage method تستقبل مننا parameter بالبيانات اللى عاوزين نبعتها إلى باقي علامات التبويب، وفي المثال دا بنبعت لها object يحتوى على اتنين من الـ properties سميناهم type و message، وكان ممكن نبعت البيانات بأى شكل تاني (مش لازم object).
بإجراء تعديل بسيط على الكود المذكور لإرسال البيانات بحيث يكون كالتالي:

نقدر نبعت رسالة من علامة تبويب إلى باقي التبويبات المفتوحة حاليا بمجرد الضغط بالماوس داخل الصفحة.
للتجربة، هنفتح علامتي تبويب مختلفتين لنفس الصفحة، وبعدها نضغط على الصفحة من أحد العلامتين، ثم نفتح الـ console في علامة التبويب التانية لنجد التالي:

وهى دى الـ event parameter اللى اتفقنا إن الـ onmessage function بتستقبلها، وهنلاقى جواها data property بتشيل البيانات اللى بعتناها من خلال الـ postMessage method.
هل نقدر نستخدم الـ Broadcast Channel API في كل المتصفحات ؟
تبعا لموقع https://caniuse.com فالـ Broadcast Channel API متاح عند حوالى 96.2% من العدد الكلي لمستخدمي المتصفحات المعروفة، بالتالي تقدر تستخدمه في تطبيقاتك بدون قلق.

وفي وجود error handling مناسب تقدر تضمن إنه مش هيسبب أى مشاكل على المتصفحات اللى مش بتدعمه.
في الختام
لـ Broadcast Channel API هي أداة قوية وفعالة للتواصل بين تبويبات المتصفح. سواء كنت عايز تعمل تزامن بيانات أو تنقل رسائل بين التبويبات.
Discussion