Ứng dụng Firebase hoạt động ngay cả khi ứng dụng của bạn tạm thời mất kết nối mạng. Chúng tôi cung cấp một số công cụ giúp theo dõi sự hiện diện và đồng bộ hoá trạng thái cục bộ với trạng thái máy chủ. Những công cụ này được giới thiệu trong tài liệu này.
Quản lý sự hiện diện
Trong các ứng dụng thời gian thực, thường hữu ích trong việc phát hiện khi nào ứng dụng kết nối và ngắt kết nối. Ví dụ: bạn có thể muốn đánh dấu người dùng là 'ngoại tuyến' khi khách hàng của họ ngắt kết nối.
Ứng dụng Cơ sở dữ liệu Firebase cung cấp các dữ liệu gốc đơn giản mà bạn có thể sử dụng để ghi vào cơ sở dữ liệu khi ứng dụng ngắt kết nối khỏi Cơ sở dữ liệu Firebase máy chủ. Các quá trình cập nhật này diễn ra dù máy khách có ngắt kết nối một cách dễ dàng hay không, để bạn có thể dựa vào các dịch vụ này để dọn dẹp dữ liệu ngay cả khi mất kết nối hoặc ứng dụng gặp sự cố. Tất cả thao tác ghi, bao gồm cả thao tác đặt, cập nhật và xoá có thể được thực hiện khi ngắt kết nối.
Dưới đây là một ví dụ đơn giản về cách ghi dữ liệu khi bị ngắt kết nối bằng cách sử dụng
Dữ liệu gốc 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!");
Cách tính năng onNgắt kết nối hoạt động
Khi bạn thiết lập một toán tử onDisconnect()
, toán tử
nằm trên máy chủ Firebase Realtime Database. Máy chủ kiểm tra bảo mật để
đảm bảo người dùng có thể thực hiện sự kiện ghi theo yêu cầu và thông báo
ứng dụng của bạn nếu ứng dụng đó không hợp lệ. Sau đó, máy chủ
sẽ giám sát kết nối. Nếu tại bất kỳ thời điểm nào kết nối hết thời gian chờ, hoặc
do máy khách Realtime Database chủ động đóng, máy chủ sẽ kiểm tra tính bảo mật
lần thứ hai (để đảm bảo thao tác vẫn hợp lệ) rồi gọi
sự kiện.
Ứng dụng của bạn có thể dùng lệnh gọi lại trong thao tác ghi
để đảm bảo onDisconnect
đã được đính kèm chính xác:
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); } });
Bạn cũng có thể huỷ một sự kiện onDisconnect
bằng cách gọi .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();
Phát hiện trạng thái kết nối
Đối với nhiều tính năng liên quan đến sự hiện diện, tính năng này rất hữu ích cho ứng dụng của bạn
biết khi nào thiết bị trực tuyến hoặc ngoại tuyến. Firebase Realtime Database
cung cấp một vị trí đặc biệt tại /.info/connected
được cập nhật mỗi khi trạng thái kết nối của ứng dụng Firebase Realtime Database
thay đổi. Bạn có thể tham khảo ví dụ sau đây:
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
là một giá trị boolean không
được đồng bộ hoá giữa Realtime Database ứng dụng vì giá trị là
phụ thuộc vào trạng thái của khách hàng. Nói cách khác, nếu một khách hàng
đọc /.info/connected
là false, giá trị này là không
đảm bảo rằng một ứng dụng riêng biệt cũng sẽ đọc giá trị "false".
Độ trễ xử lý
Dấu thời gian của máy chủ
Máy chủ Firebase Realtime Database cung cấp một cơ chế chèn
dấu thời gian được tạo trên máy chủ dưới dạng dữ liệu. Tính năng này, kết hợp với
onDisconnect
, giúp bạn dễ dàng ghi chú một cách đáng tin cậy
thời điểm ngắt kết nối ứng dụng 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);
Mặt đồng hồ
Trong khi firebase.database.ServerValue.TIMESTAMP
thì hiệu quả hơn nhiều
chính xác và phù hợp nhất với hầu hết các thao tác đọc/ghi,
Đôi khi, việc ước tính độ lệch đồng hồ của ứng dụng khách với
đối với máy chủ của Firebase Realtime Database. Bạn
có thể đính kèm lệnh gọi lại vào vị trí /.info/serverTimeOffset
để nhận giá trị, tính bằng mili giây, mà ứng dụng Firebase Realtime Database
thêm vào thời gian được báo cáo cục bộ (thời gian bắt đầu của hệ thống tính bằng mili giây) để ước tính
theo thời gian máy chủ. Lưu ý rằng độ chính xác của giá trị bù trừ này có thể bị ảnh hưởng bởi
độ trễ kết nối mạng, nên công cụ này chủ yếu hữu ích trong việc khám phá
chênh lệch lớn (> 1 giây) về thời gian đồng hồ.
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; });
Ứng dụng mẫu hiện diện
Bằng cách kết hợp các hoạt động ngắt kết nối với tính năng theo dõi trạng thái kết nối và dấu thời gian của máy chủ, bạn có thể xây dựng một hệ thống hiện diện người dùng. Trong hệ thống này, mỗi người dùng lưu trữ dữ liệu tại một vị trí cơ sở dữ liệu để cho biết liệu có Khách hàng Realtime Database đang trực tuyến. Ứng dụng đặt vị trí này thành true khi khi các thiết bị này kết nối mạng và một dấu thời gian khi chúng ngắt kết nối. Dấu thời gian này cho biết lần cuối cùng người dùng cụ thể trực tuyến.
Lưu ý rằng ứng dụng phải đưa các hoạt động ngắt kết nối vào hàng đợi trước khi người dùng được đánh dấu là trực tuyến, để tránh mọi điều kiện tranh đấu trong trường hợp khách hàng bị mất kết nối mạng trước khi có thể gửi cả hai lệnh đến máy chủ.
Dưới đây là một hệ thống đơn giản giúp xác định sự hiện diện của người dùng:
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); } });