تعمل تطبيقات Firebase حتى إذا انقطع اتصالها بالشبكة مؤقتًا. نوفّر عدة أدوات لمراقبة التواجد ومزامنة الحالة المحلية مع حالة الخادم، والتي يتم تقديمها في هذا المستند.
إدارة التواجد
غالبًا ما يكون من المفيد في تطبيقات الوقت الفعلي اكتشاف الوقت الذي يستغرقه العملاء الاتصال وقطع الاتصال. على سبيل المثال، يمكنك أن تريد وضع علامة "غير متصل" على المستخدم عندما ينقطع اتصال عميله.
يوفر عملاء قاعدة بيانات Firebase أساسيات بسيطة يمكنك استخدامها الكتابة في قاعدة البيانات عندما ينقطع اتصال العميل بقاعدة بيانات Firebase الخوادم. وتحدث هذه التحديثات سواء انفصل العميل عن الخدمة أم لا لذا يمكنك الاعتماد عليها لتنظيف البيانات حتى إذا انقطع الاتصال أو تعطل عميل ما. جميع عمليات الكتابة، بما في ذلك الإعداد وتحديثه وإزالته، عند قطع الاتصال.
فيما يلي مثال بسيط لكتابة البيانات عند الفصل باستخدام
المجموعة الأساسية onDisconnect
:
Web
import { getDatabase, ref, onDisconnect } from "firebase/database"; const db = getDatabase(); const presenceRef = ref(db, "disconnectmessage"); // Write a string when this client loses connection onDisconnect(presenceRef).set("I disconnected!");
Web
var presenceRef = firebase.database().ref("disconnectmessage"); // Write a string when this client loses connection presenceRef.onDisconnect().set("I disconnected!");
طريقة عمل ميزة on Connect
عند إنشاء عملية onDisconnect()
، يتم
يوجد على خادم Firebase Realtime Database. يفحص الخادم الأمان
وتتأكد من أن المستخدم يمكنه تنفيذ حدث الكتابة المطلوب، ويبلغ
تطبيقك إذا كان غير صالح. ثم الخادم
ويراقب الاتصال. إذا انتهت مهلة الاتصال في أي وقت أو
بشكل نشط من قِبل عميل Realtime Database، يفحص الخادم الأمان
مرة ثانية (للتأكد من أن العملية لا تزال صالحة) ثم يتم استدعاء
الحدث.
يمكن لتطبيقك استخدام الاستدعاء في عملية الكتابة.
للتأكّد من توصيل onDisconnect
بشكل صحيح:
Web
onDisconnect(presenceRef).remove().catch((err) => { if (err) { console.error("could not establish onDisconnect event", err); } });
Web
presenceRef.onDisconnect().remove((err) => { if (err) { console.error("could not establish onDisconnect event", err); } });
يمكن أيضًا إلغاء حدث "onDisconnect
" من خلال الاتصال بالرقم .cancel()
:
Web
const onDisconnectRef = onDisconnect(presenceRef); onDisconnectRef.set("I disconnected"); // some time later when we change our minds onDisconnectRef.cancel();
Web
var onDisconnectRef = presenceRef.onDisconnect(); onDisconnectRef.set("I disconnected"); // some time later when we change our minds onDisconnectRef.cancel();
اكتشاف حالة الاتصال
بالنسبة إلى العديد من الميزات المتعلّقة بالحضور، يكون ذلك مفيدًا لتطبيقك.
لمعرفة ما إذا كان متصلاً بالإنترنت أو غير متصل بالإنترنت. Firebase Realtime Database
يوفر موقعًا خاصًا في /.info/connected
والذي
يتم تعديل كل مرة يتم فيها تعديل حالة اتصال عميل Firebase Realtime Database
التغييرات. وفي ما يلي مثال لذلك:
Web
import { getDatabase, ref, onValue } from "firebase/database"; const db = getDatabase(); const connectedRef = ref(db, ".info/connected"); onValue(connectedRef, (snap) => { if (snap.val() === true) { console.log("connected"); } else { console.log("not connected"); } });
Web
var connectedRef = firebase.database().ref(".info/connected"); connectedRef.on("value", (snap) => { if (snap.val() === true) { console.log("connected"); } else { console.log("not connected"); } });
/.info/connected
هي قيمة منطقية ليست
تمت مزامنتها بين Realtime Database من العملاء لأن القيمة
يعتمد على حالة العميل. بعبارة أخرى، إذا كان أحد العملاء
تقرأ /.info/connected
على أنها false، هذا لا
ضمان قراءة عميل منفصل للخطأ أيضًا.
وقت الاستجابة
الطوابع الزمنية للخادم
توفر خوادم Firebase Realtime Database آلية لإدراج
الطوابع الزمنية التي تم إنشاؤها على الخادم كبيانات. وهذه الميزة بالإضافة إلى
onDisconnect
، طريقة سهلة لتدوين الملاحظات بشكل موثوق فيه
الوقت الذي تم فيه قطع اتصال عميل Realtime Database:
Web
import { getDatabase, ref, onDisconnect, serverTimestamp } from "firebase/database"; const db = getDatabase(); const userLastOnlineRef = ref(db, "users/joe/lastOnline"); onDisconnect(userLastOnlineRef).set(serverTimestamp());
Web
var userLastOnlineRef = firebase.database().ref("users/joe/lastOnline"); userLastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP);
انحراف الساعة
في حين أن firebase.database.ServerValue.TIMESTAMP
أكثر بكثير
ودقيقة ومفضلة لمعظم عمليات القراءة/الكتابة،
قد يكون من المفيد أحيانًا تقدير ساعة العميل
في ما يتعلق بخوادم Firebase Realtime Database. إِنْتَ
يمكن إرفاق معاودة الاتصال بالموقع الجغرافي /.info/serverTimeOffset
.
للحصول على القيمة، بالمللي ثانية، التي يستخدمها عملاء Firebase Realtime Database
تضيفه إلى الوقت المحلي المبلّغ عنه (وقت الحقبة بالمللي ثانية) لتقدير
وقت الخادم. لاحظ أن دقة هذه الإزاحة يمكن أن تتأثر
وقت استجابة الشبكة، لذا فهي مفيدة في المقام الأول لاكتشاف
اختلافات كبيرة (أكبر من ثانية واحدة) في وقت الساعة.
Web
import { getDatabase, ref, onValue } from "firebase/database"; const db = getDatabase(); const offsetRef = ref(db, ".info/serverTimeOffset"); onValue(offsetRef, (snap) => { const offset = snap.val(); const estimatedServerTimeMs = new Date().getTime() + offset; });
Web
var offsetRef = firebase.database().ref(".info/serverTimeOffset"); offsetRef.on("value", (snap) => { var offset = snap.val(); var estimatedServerTimeMs = new Date().getTime() + offset; });
نموذج تطبيق التواجد
من خلال الجمع بين عمليات قطع الاتصال ومراقبة حالة الاتصال الطوابع الزمنية للخادم، فيمكنك إنشاء نظام تواجد المستخدم. في هذا النظام، يقوم كل مستخدم بتخزين البيانات في موقع قاعدة البيانات للإشارة إلى ما إذا كان عميل واحد (Realtime Database) متصل بالإنترنت. يضبط العملاء هذا الموقع على "صحيح" عندما عند اتصالهم بالإنترنت وبطابع زمني عند قطع الاتصال. هذا الطابع الزمني تشير إلى آخر مرة كان فيها المستخدم المحدد متصلاً بالإنترنت.
تجدر الإشارة إلى أنّ تطبيقك يجب أن يضع عمليات إلغاء الربط في قائمة انتظار قبل أن يبدأ المستخدم وتمييزها عبر الإنترنت، لتجنب أي شروط سباق في حال انعقاد يتم فقدان اتصال الشبكة قبل إرسال كلا الأمرين إلى الخادم.
إليك نظام بسيط لتواجد المستخدم:
Web
import { getDatabase, ref, onValue, push, onDisconnect, set, serverTimestamp } from "firebase/database"; // Since I can connect from multiple devices or browser tabs, we store each connection instance separately // any time that connectionsRef's value is null (i.e. has no children) I am offline const db = getDatabase(); const myConnectionsRef = ref(db, 'users/joe/connections'); // stores the timestamp of my last disconnect (the last time I was seen online) const lastOnlineRef = ref(db, 'users/joe/lastOnline'); const connectedRef = ref(db, '.info/connected'); onValue(connectedRef, (snap) => { if (snap.val() === true) { // We're connected (or reconnected)! Do anything here that should happen only if online (or on reconnect) const con = push(myConnectionsRef); // When I disconnect, remove this device onDisconnect(con).remove(); // Add this device to my connections list // this value could contain info about the device or a timestamp too set(con, true); // When I disconnect, update the last time I was seen online onDisconnect(lastOnlineRef).set(serverTimestamp()); } });
Web
// Since I can connect from multiple devices or browser tabs, we store each connection instance separately // any time that connectionsRef's value is null (i.e. has no children) I am offline var myConnectionsRef = firebase.database().ref('users/joe/connections'); // stores the timestamp of my last disconnect (the last time I was seen online) var lastOnlineRef = firebase.database().ref('users/joe/lastOnline'); var connectedRef = firebase.database().ref('.info/connected'); connectedRef.on('value', (snap) => { if (snap.val() === true) { // We're connected (or reconnected)! Do anything here that should happen only if online (or on reconnect) var con = myConnectionsRef.push(); // When I disconnect, remove this device con.onDisconnect().remove(); // Add this device to my connections list // this value could contain info about the device or a timestamp too con.set(true); // When I disconnect, update the last time I was seen online lastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP); } });