تعمل تطبيقات 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 في الوقت الفعلي. يفحص الخادم الأمان
وتتأكد من أن المستخدم يمكنه تنفيذ حدث الكتابة المطلوب، ويبلغ
تطبيقك إذا كان غير صالح. ثم الخادم
ويراقب الاتصال. إذا انتهت مهلة الاتصال في أي وقت أو
بواسطة عميل قاعدة البيانات في الوقت الفعلي، فإن الخادم يفحص أمان
مرة ثانية (للتأكد من أن العملية لا تزال صالحة) ثم يتم استدعاء
الحدث.
يمكن لتطبيقك استخدام الاستدعاء في عملية الكتابة.
للتأكّد من توصيل 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 في الوقت الفعلي
يوفر موقعًا خاصًا في /.info/connected
يتم تعديل كل مرة يتم فيها تعديل حالة اتصال عميل قاعدة بيانات Firebase في الوقت الفعلي
التغييرات. وفي ما يلي مثال لذلك:
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
هي قيمة منطقية ليست
متزامنة بين عملاء قاعدة البيانات في الوقت الفعلي لأن القيمة
يعتمد على حالة العميل. بعبارة أخرى، إذا كان أحد العملاء
تقرأ /.info/connected
على أنها false، هذا لا
ضمان قراءة عميل منفصل للخطأ أيضًا.
وقت الاستجابة
الطوابع الزمنية للخادم
وتوفر خوادم قاعدة بيانات Firebase في الوقت الفعلي آلية لإدراج
الطوابع الزمنية التي تم إنشاؤها على الخادم كبيانات. وهذه الميزة بالإضافة إلى
onDisconnect
، طريقة سهلة لتدوين الملاحظات بشكل موثوق فيه
الوقت الذي تم فيه قطع اتصال عميل قاعدة البيانات في الوقت الفعلي:
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 في الوقت الفعلي. إِنْتَ
يمكن إرفاق معاودة الاتصال بالموقع الجغرافي /.info/serverTimeOffset
.
وذلك من أجل الحصول على القيمة بالمللي ثانية التي يستخدمها عملاء قاعدة بيانات Firebase في الوقت الفعلي
تضيفه إلى الوقت المحلي المبلّغ عنه (وقت الحقبة بالمللي ثانية) لتقدير
وقت الخادم. لاحظ أن دقة هذه الإزاحة يمكن أن تتأثر
وقت استجابة الشبكة، لذا فهي مفيدة في المقام الأول لاكتشاف
اختلافات كبيرة (أكبر من ثانية واحدة) في وقت الساعة.
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; });
نموذج تطبيق التواجد
من خلال الجمع بين عمليات قطع الاتصال ومراقبة حالة الاتصال الطوابع الزمنية للخادم، فيمكنك إنشاء نظام تواجد المستخدم. في هذا النظام، يقوم كل مستخدم بتخزين البيانات في موقع قاعدة البيانات للإشارة إلى ما إذا كان برنامج قاعدة البيانات في الوقت الفعلي متصل بالإنترنت. يضبط العملاء هذا الموقع على "صحيح" عندما عند اتصالهم بالإنترنت وبطابع زمني عند قطع الاتصال. هذا الطابع الزمني تشير إلى آخر مرة كان فيها المستخدم المحدد متصلاً بالإنترنت.
تجدر الإشارة إلى أنّ تطبيقك يجب أن يضع عمليات إلغاء الربط في قائمة انتظار قبل أن يبدأ المستخدم وتمييزها عبر الإنترنت، لتجنب أي شروط سباق في حال انعقاد يتم فقدان اتصال الشبكة قبل إرسال كلا الأمرين إلى الخادم.
إليك نظام بسيط لتواجد المستخدم:
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); } });