在 Cloud Firestore 中建構產品

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

舉例來說,如果您要建構社群網路等應用程式,或部署一整套 IoT 裝置,可以利用這項資訊顯示線上的好友清單,讓使用者可以與他們即時通訊,或是依據「上次看到」排序 IoT 裝置。

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} 文件,並使用資料變更 UI,以反映連線狀態。

網路

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 事件中卸載。
  • 連線能力:這種實作方式會評估與 Realtime 的連線能力 資料庫,而非 Cloud Firestore。如果連線 每個資料庫的狀態都不同,這項解決方案可能會回報 狀態不正確
  • Android:在 Android 上,如果 60 秒內沒有任何操作,即時資料庫就會與後端中斷連線。閒置時表示沒有開啟事件監聽器 或待處理的作業為確保連線保持開啟,建議您在 .info/connected 以外的路徑中新增值事件監聽器。舉例來說, 可FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() 在每個工作階段開始時啟動若需更多資訊,請參閲 偵測連線狀態