即使您的應用程式暫時失去網路連線,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!");
如何中斷連線
建立 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); } });
您也可以呼叫 .cancel()
來取消 onDisconnect
事件:
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,這不會
確保個別用戶端也會讀取 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 用戶端的價值 (以毫秒為單位)
與當地回報時間相加 (以毫秒為單位),進行估算
伺服器時間請注意,位移的精確度會受到
因此非常適合用於探索網路延遲
時鐘時間出現明顯差異 (> 1 秒)。
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」用戶端在線上。用戶端在下列情況會將這個位置設為 true 以及連線中斷時的時間戳記。這個時間戳記 表示特定使用者上次上線的時間。
請注意,應用程式應在使用者中斷連線前,將中斷作業排入佇列 線上標記,以避免客戶的 在能將兩個指令傳送至伺服器之前,網路連線中斷。
這類簡易的使用者線上狀態系統如下:
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); } });