Aplikasi Firebase tetap berfungsi meskipun aplikasi Anda kehilangan koneksi jaringan untuk sementara. Kami menyediakan beberapa alat untuk memantau kehadiran dan menyinkronkan status lokal dengan status server, yang diperkenalkan dalam dokumen ini.
Mengelola Kehadiran
Pada aplikasi real-time, mendeteksi kapan klien membuat dan memutus koneksi sering kali bermanfaat. Misalnya, mungkin Anda ingin menandai pengguna sebagai 'offline' saat kliennya memutus koneksi.
Klien Firebase Database menyediakan sejumlah primitif sederhana yang dapat Anda gunakan untuk menulis ke database saat suatu klien memutuskan koneksi ke server Firebase Database. Update ini akan terjadi, terlepas dari apakah klien memutuskan koneksi secara bersih atau tidak, sehingga Anda dapat mengandalkan update ini untuk membersihkan data, meskipun koneksi terputus atau klien mengalami error. Semua operasi tulis, termasuk penyetelan, update, dan penghapusan, dapat dilakukan setelah koneksi terputus.
Berikut contoh sederhana penulisan data setelah koneksi diputus menggunakan primitif 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!");
Cara Kerja onDisconnect
Saat Anda membuat operasi onDisconnect()
, operasi tersebut akan berlangsung di server Firebase Realtime Database. Server akan memeriksa keamanan untuk memastikan
bahwa pengguna dapat menjalankan peristiwa tulis yang diminta, dan memberi tahu
aplikasi Anda jika operasi tersebut tidak valid. Selanjutnya, server akan
memantau koneksinya. Jika waktu koneksi habis, atau koneksi ditutup secara aktif
oleh klien Realtime Database, server akan memeriksa keamanan
sekali lagi (untuk memastikan operasi masih valid), kemudian memanggil
peristiwa tersebut.
Aplikasi Anda dapat menggunakan callback di operasi tulis untuk memastikan onDisconnect
terpasang dengan benar:
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); } });
Peristiwa onDisconnect
juga dapat dibatalkan dengan memanggil .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();
Mendeteksi Status Koneksi
Untuk banyak fitur yang terkait dengan kehadiran, ada baiknya jika aplikasi mengetahui
apakah status koneksi sedang online atau offline. Firebase Realtime Database
menyediakan lokasi khusus di /.info/connected
yang
diperbarui setiap kali status koneksi klien Firebase Realtime Database
berubah. Berikut ini contohnya:
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
adalah nilai boolean yang tidak disinkronkan antarklien Realtime Database karena nilainya bergantung pada status klien. Dengan kata lain, jika satu klien membaca /.info/connected
sebagai 'false', tidak ada jaminan bahwa klien lain juga akan membacanya sebagai 'false'.
Menangani Latensi
Stempel Waktu Server
Server Firebase Realtime Database memberikan mekanisme
untuk menyisipkan stempel waktu yang dibuat di server sebagai data. Fitur ini, bersama dengan onDisconnect
, memberikan cara mudah dan andal untuk mencatat kapan koneksi klien Realtime Database diputus:
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
Meskipun firebase.database.ServerValue.TIMESTAMP
jauh lebih akurat
dan lebih cocok untuk sebagian besar operasi baca/tulis,
terkadang ada baiknya memperkirakan clock skew klien
terhadap server Firebase Realtime Database. Anda
dapat menambahkan callback ke lokasi /.info/serverTimeOffset
untuk mendapatkan nilai, dalam milidetik, yang ditambahkan oleh klien Firebase Realtime Database
ke waktu lokal yang dilaporkan (waktu epoch dalam milidetik) untuk memperkirakan
waktu server. Perlu diperhatikan bahwa akurasi selisih ini dapat dipengaruhi oleh latensi jaringan, sehingga hanya bermanfaat untuk menemukan selisih waktu jam yang besar (> 1 detik).
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; });
Contoh Aplikasi Kehadiran
Dengan menggabungkan operasi pemutusan koneksi dengan pemantauan status koneksi dan stempel waktu server, Anda dapat membuat suatu sistem kehadiran pengguna. Dalam sistem ini, setiap pengguna menyimpan data di lokasi basis data untuk menunjukkan apakah klien Realtime Database sedang online atau tidak. Klien akan menetapkan lokasi ini ke benar (true) ketika mulai online dan ke stempel waktu ketika memutuskan koneksi. Stempel waktu ini menunjukkan kapan terakhir kali pengguna tersebut online.
Perlu diperhatikan bahwa aplikasi Anda harus mengantrekan operasi pemutusan koneksi sebelum pengguna ditandai sebagai online, untuk menghindari kondisi race yang dapat terjadi jika koneksi jaringan klien terputus sebelum kedua perintah dapat dikirimkan ke server.
Berikut adalah contoh sederhana dari sistem kehadiran pengguna:
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); } });