แอปพลิเคชัน Firebase จะทำงานได้แม้ว่าแอปจะสูญเสียการเชื่อมต่อเครือข่ายชั่วคราว เรามีเครื่องมือหลายอย่างสำหรับการตรวจสอบสถานะและการซิงค์สถานะในเครื่องกับสถานะเซิร์ฟเวอร์ ซึ่งจะแนะนำในเอกสารนี้
การจัดการการตรวจหาบุคคลในบ้าน
ในแอปพลิเคชันแบบเรียลไทม์ การตรวจหาเมื่อไคลเอ็นต์ เชื่อมต่อและยกเลิกการเชื่อมต่อมักจะมีประโยชน์ เช่น คุณอาจ ต้องการทำเครื่องหมายผู้ใช้เป็น "ออฟไลน์" เมื่อไคลเอ็นต์ของผู้ใช้ยกเลิกการเชื่อมต่อ
ไคลเอ็นต์ฐานข้อมูล Firebase มี Primitive อย่างง่ายที่คุณใช้เขียนไปยังฐานข้อมูลได้เมื่อไคลเอ็นต์ยกเลิกการเชื่อมต่อจากเซิร์ฟเวอร์ฐานข้อมูล 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
เมื่อคุณสร้างการดำเนินการ onDisconnect()
การดำเนินการ
จะอยู่ในเซิร์ฟเวอร์ Firebase Realtime Database เซิร์ฟเวอร์จะตรวจสอบความปลอดภัยเพื่อให้แน่ใจว่าผู้ใช้สามารถดำเนินการเขียนเหตุการณ์ที่ขอได้ และจะแจ้งให้แอปของคุณทราบหากไม่ถูกต้อง จากนั้นเซิร์ฟเวอร์จะ
ตรวจสอบการเชื่อมต่อ หากการเชื่อมต่อหมดเวลาหรือRealtime Databaseไคลเอ็นต์ปิดการเชื่อมต่อโดยตรง
เซิร์ฟเวอร์จะตรวจสอบความปลอดภัยเป็นครั้งที่ 2 (เพื่อให้แน่ใจว่าการดำเนินการยังคงใช้ได้) จากนั้นจะเรียกใช้
เหตุการณ์
แอปของคุณสามารถใช้การเรียกกลับในการดำเนินการเขียน
เพื่อให้แน่ใจว่าได้แนบ 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); } });
คุณยังยกเลิกonDisconnect
กิจกรรมได้โดยโทรหา.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();
การตรวจหาสถานะการเชื่อมต่อ
สำหรับฟีเจอร์ที่เกี่ยวข้องกับการแสดงตนหลายอย่าง การที่แอป
ทราบว่าแอปออนไลน์หรือออฟไลน์เมื่อใดจะเป็นประโยชน์ 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
เป็นเท็จ ก็ไม่ได้หมายความว่าไคลเอ็นต์อื่นจะอ่านเป็นเท็จด้วย
เวลาในการตอบสนอง
การประทับเวลาของเซิร์ฟเวอร์
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);
Clock Skew
แม้ว่า firebase.database.ServerValue.TIMESTAMP
จะมีความแม่นยำมากกว่า
และเหมาะสำหรับการอ่าน/เขียนส่วนใหญ่ แต่บางครั้งการประมาณค่าความคลาดเคลื่อนของนาฬิกาไคลเอ็นต์
เมื่อเทียบกับเซิร์ฟเวอร์ของ Firebase Realtime Database ก็อาจมีประโยชน์ คุณ
สามารถแนบฟังก์ชันเรียกกลับไปยังตำแหน่ง /.info/serverTimeOffset
เพื่อรับค่าเป็นมิลลิวินาทีที่ไคลเอ็นต์ Firebase Realtime Database
เพิ่มลงในเวลาที่รายงานในเครื่อง (เวลา Epoch เป็นมิลลิวินาที) เพื่อประมาณ
เวลาของเซิร์ฟเวอร์ โปรดทราบว่าความแม่นยำของออฟเซ็ตนี้อาจได้รับผลกระทบจาก
เวลาในการตอบสนองของเครือข่าย ดังนั้นจึงมีประโยชน์หลักๆ ในการค้นหา
ความคลาดเคลื่อนขนาดใหญ่ (> 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; });
แอป Presence ตัวอย่าง
การรวมการดำเนินการยกเลิกการเชื่อมต่อกับการตรวจสอบสถานะการเชื่อมต่อและ การประทับเวลาของเซิร์ฟเวอร์จะช่วยให้คุณสร้างระบบสถานะของผู้ใช้ได้ ในระบบนี้ ผู้ใช้แต่ละรายจะจัดเก็บข้อมูลไว้ที่ตำแหน่งฐานข้อมูลเพื่อระบุว่าไคลเอ็นต์ Realtime Database ออนไลน์หรือไม่ ไคลเอ็นต์จะตั้งค่าตำแหน่งนี้เป็น "จริง" เมื่อ ออนไลน์ และตั้งค่าการประทับเวลาเมื่อยกเลิกการเชื่อมต่อ การประทับเวลานี้ ระบุเวลาล่าสุดที่ผู้ใช้ออนไลน์
โปรดทราบว่าแอปควรจัดคิวการดำเนินการยกเลิกการเชื่อมต่อก่อนที่จะ ทำเครื่องหมายผู้ใช้ออนไลน์ เพื่อหลีกเลี่ยงการแข่งขันในกรณีที่ไคลเอ็นต์ สูญเสียการเชื่อมต่อเครือข่ายก่อนที่จะส่งทั้ง 2 คำสั่งไปยังเซิร์ฟเวอร์ได้
ระบบการแสดงข้อมูลของผู้ใช้แบบง่ายมีดังนี้
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); } });