在 Cloud Firestore 中建構產品

視您所開發的應用程式類型而定,您可能會發現 哪些使用者或裝置經常在線上 (也就是 偵測是否「存在」

舉例來說,如果您正在建構像是社交網路之類的應用程式 就能運用這項資訊 可以免費進行即時通訊的好友,或按照 「上次上線」。

Cloud Firestore 並未原生支援狀態,但您可以利用其他 Firebase 產品建構狀態系統。

解決方案:Cloud Functions 搭配即時資料庫

將「Cloud Firestore」連結至 Firebase 即時資料庫的原生資料庫 此時請使用 Cloud Functions

透過即時資料庫回報連線狀態,然後使用 Cloud Functions 來 以反射該資料為 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 函式,讓所有其他裝置存取 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 狀態寫入作業僅能在本機環境中寫入,恢復連線後就不會同步。給計數器 這將會使用 Cloud 函式即時監控 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() 在每個工作階段開始時啟動若需更多資訊,請參閲 偵測連線狀態