Włączanie funkcji offline w JavaScripcie

Aplikacje Firebase działają nawet wtedy, gdy aplikacja tymczasowo utraci 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 Bazy danych czasu rzeczywistego Firebase. 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ętego przez klienta Bazy danych czasu rzeczywistego, 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. Baza danych czasu rzeczywistego Firebase udostępnia specjalną lokalizację pod adresem /.info/connected, która jest aktualizowany za każdym razem, gdy stan połączenia klienta Bazy danych czasu rzeczywistego Firebase jest aktualizowany 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 jest synchronizowana między klientami Bazy danych czasu rzeczywistego, 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 Bazy danych czasu rzeczywistego Firebase oferują mechanizm wstawiania sygnatur czasowych wygenerowanych na serwerze jako dane. Ta funkcja w połączeniu z onDisconnect umożliwia łatwe zanotowanie moment odłączenia klienta Bazy danych czasu rzeczywistego:

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 kontekście serwerów Bazy danych czasu rzeczywistego Firebase. Ty może dołączyć oddzwonienie do lokalizacji /.info/serverTimeOffset aby uzyskać w milisekundach wartość klientów Bazy danych czasu rzeczywistego Firebase 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 Klient Bazy danych czasu rzeczywistego 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);
  }
});