Włączanie funkcji offline w JavaScripcie

Aplikacje Firebase działają nawet wtedy, gdy tymczasowo utracą połączenie sieciowe. Udostępniamy kilka narzędzi do monitorowania obecności i synchronizowania stanu lokalnego ze stanem serwera, które opisujemy w tym dokumencie.

Zarządzanie obecnością

W aplikacjach działających w czasie rzeczywistym często przydaje się możliwość wykrywania, nawiąż i rozłącz. Możesz na przykład chcesz oznaczyć użytkownika jako użytkownika offline. gdy klient się rozłącza.

Klienty bazy danych Firebase udostępniają proste elementy podstawowe umożliwiające zapisywanie w bazie danych, gdy klient odłączy się od bazy danych Firebase serwerów. Te aktualizacje pojawiają się niezależnie od tego, czy klient się rozłącza, czy nie, Możesz na nich polegać, jeśli wyczyścisz dane nawet wtedy, gdy połączenie zostanie przerwane lub po awarii klienta. Wszystkie operacje zapisu, w tym ustawienia aktualizacji i usuwania można przeprowadzić po rozłączeniu.

Oto prosty przykład zapisywania danych po odłączeniu za pomocą polecenia Element podstawowy 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!");

Jak onOdłącz działa?

Gdy utworzysz operację onDisconnect(), działa na serwerze Firebase Realtime Database. Serwer sprawdza zabezpieczenia Upewnij się, że użytkownik może wykonać żądane zdarzenie zapisu oraz informuje aplikacji, jeśli jest ona nieprawidłowa. Serwer oraz monitoruje połączenie. jeśli w którymkolwiek momencie połączenie zostanie przekroczone lub będzie aktywnie zamknięte przez klienta Realtime Database, serwer sprawdza zabezpieczenia po raz drugi (aby upewnić się, że operacja jest nadal prawidłowa), a następnie wywołuje do zdarzenia.

Aplikacja może używać wywołania zwrotnego podczas zapisu aby upewnić się, że łącznik onDisconnect został prawidłowo podłączony:

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);
  }
});

Wydarzenie onDisconnect można też anulować, dzwoniąc pod numer .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();

Wykrywam stan połączenia

W przypadku wielu funkcji związanych z obecnością opcja jest przydatna w aplikacji czy jest online czy offline. Firebase Realtime Database udostępnia specjalną lokalizację pod adresem /.info/connected, która jest aktualizowany za każdym razem, gdy stan połączenia klienta Firebase Realtime Database zmian. Oto przykład:

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 jest wartością logiczną, która nie jest zsynchronizowana między Realtime Database klientami, ponieważ wartość to w zależności od stanu klienta. Innymi słowy, jeśli jeden klient odczytuje /.info/connected jako fałsz, to nie jest zagwarantowanie, że oddzielny klient również odczyta wartość „false” (fałsz).

Czas oczekiwania na obsługę

Sygnatury czasowe serwera

Serwery Firebase Realtime Database zapewniają mechanizm wstawiania sygnatur czasowych wygenerowanych na serwerze jako dane. Ta funkcja w połączeniu z onDisconnect umożliwia łatwe zanotowanie godzina rozłączenia klienta 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);

Zniekształcenie zegara

firebase.database.ServerValue.TIMESTAMP to znacznie więcej dokładne i zalecane w większości operacji odczytu/zapisu, czasami może być przydatne do oszacowania zniekształcenia zegara klienta, w odniesieniu do serwerów Firebase Realtime Database. Ty może dołączyć oddzwonienie do lokalizacji /.info/serverTimeOffset aby uzyskać w milisekundach wartość klientów Firebase Realtime Database dodaj do szacunkowego czasu raportowania lokalnego (czasu epoki w milisekundach) czas serwera. Pamiętaj, że na dokładność przesunięcia może mieć wpływ opóźnienia sieciowe, co przydaje się przede wszystkim do wykrywania duże (> 1 sekundę) rozbieżności w czasie zegara.

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;
});

Przykładowa aplikacja Obecność

Łącząc operacje rozłączania z monitorowaniem stanu połączenia sygnatury czasowe serwera, możesz utworzyć system wykrywania obecności użytkowników. W tym systemie każdy użytkownik przechowuje dane w lokalizacji bazy danych, aby wskazać, czy Realtime Database klient jest online. Klienci ustawili tę lokalizację na Prawda, gdy: kiedy przechodzą do trybu online, oraz podaj sygnaturę czasową po rozłączeniu. Ta sygnatura czasowa wskazuje, kiedy dany użytkownik ostatnio był online.

Pamiętaj, że aplikacja powinna zakoleć operacje rozłączania, zanim użytkownik oznaczone jako online, co pozwala uniknąć wyścigów w przypadku, gdy utracisz połączenie sieciowe, zanim możliwe będzie wysłanie obu poleceń do serwera.

Oto prosty system wykrywania obecności użytkowników:

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);
  }
});