تعزيز حضورك في Cloud Firestore

بناءً على نوع التطبيق الذي تنشئه، قد تجد أنه من المفيد اكتشاف المستخدمين أو الأجهزة المتصلة بالإنترنت بشكل نشط — أو ما يُعرف باسم "التواجد".

على سبيل المثال، إذا كنت تنشئ تطبيقًا مثل شبكة اجتماعية أو تنشر لمجموعة من أجهزة إنترنت الأشياء، يمكنك استخدام هذه المعلومات لعرض قائمة الأصدقاء المتاحون على الإنترنت والدردشة مجانًا، أو يصنفون أجهزة إنترنت الأشياء (IoT) حسب "شوهد آخر مرة".

لا تتيح منصة Cloud Firestore ميزة "استشعار تواجد الأفراد في المنزل" في الأصل، ولكن يمكنك إجراء ذلك. الاستفادة من منتجات Firebase الأخرى لبناء نظام للتواجد.

الحل: دوال السحابة الإلكترونية باستخدام قاعدة بيانات "الوقت الفعلي"

لربط Cloud Firestore بالأداة الأصلية لقاعدة بيانات Firebase في الوقت الفعلي الحضور، استخدام وظائف السحابة.

استخدِم "قاعدة البيانات في الوقت الفعلي" للإبلاغ عن حالة الاتصال، ثم استخدِم دوال Cloud من أجل النسخ المطابق لهذه البيانات في Cloud Firestore.

استخدام التواجد في قاعدة بيانات الوقت الفعلي

أولاً، ضع في اعتبارك كيف يعمل نظام التواجد التقليدي في قاعدة البيانات في الوقت الفعلي.

الويب

// Fetch the current user's ID from Firebase Authentication.
var uid = firebase.auth().currentUser.uid;

// Create a reference to this user's specific status node.
// This is where we will store data about being online/offline.
var userStatusDatabaseRef = firebase.database().ref('/status/' + uid);

// We'll create two constants which we will write to 
// the Realtime database when this device is offline
// or online.
var isOfflineForDatabase = {
    state: 'offline',
    last_changed: firebase.database.ServerValue.TIMESTAMP,
};

var isOnlineForDatabase = {
    state: 'online',
    last_changed: firebase.database.ServerValue.TIMESTAMP,
};

// Create a reference to the special '.info/connected' path in 
// Realtime Database. This path returns `true` when connected
// and `false` when disconnected.
firebase.database().ref('.info/connected').on('value', function(snapshot) {
    // If we're not currently connected, don't do anything.
    if (snapshot.val() == false) {
        return;
    };

    // If we are currently connected, then use the 'onDisconnect()' 
    // method to add a set which will only trigger once this 
    // client has disconnected by closing the app, 
    // losing internet, or any other means.
    userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() {
        // The promise returned from .onDisconnect().set() will
        // resolve as soon as the server acknowledges the onDisconnect() 
        // request, NOT once we've actually disconnected:
        // https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect

        // We can now safely set ourselves as 'online' knowing that the
        // server will mark us as offline once we lose connection.
        userStatusDatabaseRef.set(isOnlineForDatabase);
    });
});

هذا المثال هو نظام كامل للتواجد في قاعدة البيانات في الوقت الفعلي. يعالج العديد من حالات انقطاع الاتصال والأعطال وما إلى ذلك.

جارٍ الاتصال بجهاز Cloud Firestore

لتنفيذ حل مشابه في Cloud Firestore، استخدِم الطريقة نفسها كود قاعدة بيانات الوقت الفعلي، ثم استخدم Cloud Functions للاحتفاظ بقاعدة البيانات في الوقت الفعلي تمت مزامنة Cloud Firestore.

أضِف قاعدة بيانات الوقت الفعلي إلى مشروعك، إذا لم يسبق لك إجراء ذلك. وتضمين حل الحضور المذكور أعلاه.

بعد ذلك، ستتم مزامنة حالة التواجد مع Cloud Firestore من خلال الطرق التالية:

  1. محليًا، إلى ذاكرة التخزين المؤقت لـ Cloud Firestore في الجهاز غير المتصل حتى يتمكن التطبيق يعرف أنه غير متصل بالإنترنت.
  2. وعلى الصعيد العالمي، يمكن استخدام وظيفة السحابة الإلكترونية حتى يتسنى لجميع الأجهزة الأخرى الوصول إلى Cloud Firestore يدرك أنّ هذا الجهاز تحديدًا غير متصل بالإنترنت.

جارٍ تعديل ذاكرة التخزين المؤقت على جهاز "Cloud Firestore"

لنلقِ نظرة على التغييرات المطلوبة لتنفيذ المشكلة الأولى، وهي: ذاكرة التخزين المؤقت المحلية لـ Cloud Firestore.

الويب

// ...
var userStatusFirestoreRef = firebase.firestore().doc('/status/' + uid);

// Firestore uses a different server timestamp value, so we'll 
// create two more constants for Firestore state.
var isOfflineForFirestore = {
    state: 'offline',
    last_changed: firebase.firestore.FieldValue.serverTimestamp(),
};

var isOnlineForFirestore = {
    state: 'online',
    last_changed: firebase.firestore.FieldValue.serverTimestamp(),
};

firebase.database().ref('.info/connected').on('value', function(snapshot) {
    if (snapshot.val() == false) {
        // Instead of simply returning, we'll also set Firestore's state
        // to 'offline'. This ensures that our Firestore cache is aware
        // of the switch to 'offline.'
        userStatusFirestoreRef.set(isOfflineForFirestore);
        return;
    };

    userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() {
        userStatusDatabaseRef.set(isOnlineForDatabase);

        // We'll also add Firestore set here for when we come online.
        userStatusFirestoreRef.set(isOnlineForFirestore);
    });
});

من خلال هذه التغييرات، نحرص على أن تكون الولاية المحلية في Cloud Firestore هي دائمًا يعكس حالة اتصال/عدم اتصال الجهاز. هذا يعني أنه يمكنك الاستماع إلى مستند واحد (/status/{uid}) واستخدام البيانات لتغيير واجهة المستخدم لإظهار عملية الربط الحالة.

الويب

userStatusFirestoreRef.onSnapshot(function(doc) {
    var isOnline = doc.data().state == 'online';
    // ... use isOnline
});

جارٍ تحديث "Cloud Firestore" على مستوى العالم

على الرغم من أن طلبنا يقدم إلى نفسه تقريرًا عن التواجد عبر الإنترنت بشكل صحيح، إلا أن هذه الحالة لن تكون دقيقة في تطبيقات Cloud Firestore الأخرى حتى الآن لأن وضعنا "بلا اتصال بالإنترنت" كتابة الحالة يكون محليًا فقط ولن تتم مزامنته عند استعادة الاتصال. للاعتراض سنستخدم دالة السحابة الإلكترونية التي تراقب مسار status/{uid} في الوقت الفعلي قاعدة البيانات. عند تغيير قيمة "قاعدة البيانات في الوقت الفعلي"، ستتم مزامنة القيمة مع Cloud Firestore حتى يتسنى لجميع المستخدمين الحالات صحيحة.

Node.js

firebase.firestore().collection('status')
    .where('state', '==', 'online')
    .onSnapshot(function(snapshot) {
        snapshot.docChanges().forEach(function(change) {
            if (change.type === 'added') {
                var msg = 'User ' + change.doc.id + ' is online.';
                console.log(msg);
                // ...
            }
            if (change.type === 'removed') {
                var msg = 'User ' + change.doc.id + ' is offline.';
                console.log(msg);
                // ...
            }
        });
    });

بعد نشر هذه الوظيفة، سيكون لديك نظام كامل قيد التشغيل مع Cloud Firestore. فيما يلي مثال على المراقبة لأي مستخدم الاتصال بالإنترنت أو قطع الاتصال بالإنترنت باستخدام طلب بحث where().

الويب

firebase.firestore().collection('status')
    .where('state', '==', 'online')
    .onSnapshot(function(snapshot) {
        snapshot.docChanges().forEach(function(change) {
            if (change.type === 'added') {
                var msg = 'User ' + change.doc.id + ' is online.';
                console.log(msg);
                // ...
            }
            if (change.type === 'removed') {
                var msg = 'User ' + change.doc.id + ' is offline.';
                console.log(msg);
                // ...
            }
        });
    });

القيود

إنّ استخدام "قاعدة البيانات في الوقت الفعلي" لإضافة بيانات تواجد الأفراد في تطبيق Cloud Firestore هو وقابلة للتطوير وفعالة ولكن لها بعض القيود:

  • ارتداد: عند الاستماع إلى تغييرات في الوقت الفعلي في Cloud Firestore، من المحتمل أن يؤدي هذا الحل إلى تشغيل العديد التغييرات. إذا أدّت هذه التغييرات إلى ظهور أحداث أكثر مما تريد، يمكنك يدويًا التراجُع عن أحداث Cloud Firestore
  • الاتصال: تقيس طريقة التنفيذ هذه إمكانية الاتصال بخدمة "الوقت الفعلي". قاعدة البيانات، وليس لـ Cloud Firestore. إذا كان الاتصال الخاصة بكل قاعدة بيانات هي نفسها، فقد يبلغ هذا الحل حالة تواجد الأفراد في المنزل غير صحيحة.
  • Android: في نظام Android، يتم إلغاء ربط قاعدة بيانات الوقت الفعلي الخلفية بعد 60 ثانية من عدم النشاط. عدم النشاط يعني عدم توفّر مستمعين متاحين أو العمليات المعلّقة. لإبقاء الاتصال مفتوحًا، ننصحك بإضافة أداة معالجة حدث القيمة إلى مسار بجانب .info/connected. على سبيل المثال تنفيذ FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() في بداية كل جلسة. لمزيد من المعلومات، يُرجى مراجعة اكتشاف حالة الاتصال: