Aktywatory bazy danych czasu rzeczywistego


Dzięki Cloud Functions możesz obsługiwać zdarzenia w Baza danych czasu rzeczywistego Firebase bez konieczności aktualizowania kodu klienta. Cloud Functions umożliwia uruchamianie operacji w bazie danych czasu rzeczywistego z pełną obsługą administracyjną i zapewnia przetwarzanie każdej zmiany w Bazie danych czasu rzeczywistego poszczególne osoby. Zmiany w Bazie danych czasu rzeczywistego Firebase możesz wprowadzać za pomocą DataSnapshot lub za pomocą pakietu Admin SDK.

W typowym cyklu życia funkcja Bazy danych czasu rzeczywistego Firebase wykonuje te czynności:

  1. Oczekiwanie na zmiany konkretnej lokalizacji Bazy danych czasu rzeczywistego.
  2. Jest wywoływane, gdy zdarzenie występuje i wykonuje swoje zadania (zobacz sekcję Co mogę zrobić w Cloud Functions?. przypadków użycia).
  3. Odbiera obiekt danych zawierający zrzut zapisanych danych w określonym dokumencie.

Aktywowanie funkcji Bazy danych czasu rzeczywistego

Tworzenie nowych funkcji dla zdarzeń w Bazie danych czasu rzeczywistego dzięki functions.database. Do kontrolować, kiedy funkcja ma się uruchamiać, określić jeden z modułów obsługi zdarzeń. określ ścieżkę Bazy danych czasu rzeczywistego, w której będzie nasłuchiwać zdarzeń.

Ustawianie modułu obsługi zdarzeń

Funkcje umożliwiają obsługę zdarzeń Bazy danych czasu rzeczywistego na 2 poziomach dokładności: możesz nasłuchiwać wyłącznie tworzenia, aktualizowania i zdarzeń usuwania. Możesz też nasłuchiwać dowolnej zmiany ścieżki. Cloud Functions obsługuje te moduły obsługi zdarzeń w bazie danych czasu rzeczywistego:

  • onWrite(), który jest wyzwalany, gdy dane są tworzone, aktualizowane lub usuwane w bazie danych czasu rzeczywistego.
  • onCreate(), który jest wyzwalany po utworzeniu nowych danych w bazie danych czasu rzeczywistego.
  • onUpdate(), który jest wyzwalany po zaktualizowaniu danych w Bazie danych czasu rzeczywistego .
  • onDelete(), które jest aktywowane, gdy dane zostaną usunięte z Bazy danych czasu rzeczywistego .

Podaj instancję i ścieżkę

Aby kontrolować, kiedy i gdzie ma być uruchamiana Twoja funkcja, wywołaj ref(path) , aby podać ścieżkę i opcjonalnie określić instancję Bazy danych czasu rzeczywistego dzięki instance('INSTANCE_NAME'). Jeśli nie chcesz w przypadku określonej instancji funkcja zostanie wdrożona w domyślnej instancji Bazy danych czasu rzeczywistego w projekt Firebase. Na przykład:

  • Domyślna instancja bazy danych czasu rzeczywistego: functions.database.ref('/foo/bar')
  • Instancja o nazwie „my-app-db-2”: functions.database.instance('my-app-db-2').ref('/foo/bar')

Te metody kierują funkcję do obsługi zapisów na określonej ścieżce w obrębie instancję Bazy danych czasu rzeczywistego. specyfikacje ścieżki pasują do wszystkich zapisów, które dotykają ścieżki, w tym zapisy które dzieje się w dowolnym miejscu pod nią. Jeśli ustawisz ścieżkę dla Twojej funkcji jako /foo/bar, pasuje do zdarzeń w obu tych lokalizacjach:

 /foo/bar
 /foo/bar/baz/really/deep/path

W obu tych przypadkach Firebase interpretuje, że zdarzenie ma miejsce /foo/bar, a dane zdarzenia zawierają stare i nowe dane są dostępne na stronie /foo/bar. Jeśli dane zdarzenia są duże, rozważ użycie wielu funkcji na głębszych ścieżkach zamiast jednej w pobliżu rdzenia bazy danych. Aby uzyskać najlepszą skuteczność, wyślij tylko żądanie dane na najgłębszym możliwym poziomie.

Komponent ścieżki możesz określić jako symbol wieloznaczny, umieszczając w komponencie klamrowym. nawiasy; Wyrażenie ref('foo/{bar}') odpowiada dowolnemu elementowi podrzędnemu z /foo. Wartości tych komponenty ścieżki z symbolem wieloznacznym są dostępne w EventContext.params funkcji. W tym przykładzie wartość jest dostępna jako context.params.bar

Ścieżki z symbolami wieloznacznymi mogą pasować do wielu zdarzeń z jednego zapisu. Wstawienie

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

dwukrotnie pasuje do ścieżki "/foo/{bar}": raz z "hello": "world" i jeszcze raz w grupie "firebase": "functions".

Obsługa danych zdarzenia

Podczas obsługi zdarzenia Bazy danych czasu rzeczywistego zwracany obiekt danych to DataSnapshot W przypadku zdarzeń onWrite i onUpdate wartość Pierwszy parametr to obiekt Change, który zawiera 2 zrzuty reprezentujących stan danych przed oraz po zdarzeniu aktywującym. W przypadku zdarzeń onCreate i onDelete: zwracany obiekt danych to zrzut utworzonych lub usuniętych danych.

W tym przykładzie funkcja pobiera zrzut dysku dla: w podanej ścieżce, zamienia ciąg znaków w tej lokalizacji na wielkie litery, i zapisuje zmodyfikowany ciąg w bazie danych:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

Uzyskiwanie dostępu do informacji uwierzytelniających użytkowników

Źródło: EventContext.auth i EventContext.authType, masz dostęp informacje o użytkowniku, w tym o jego uprawnieniach, funkcji. Jest to pomocne przy egzekwowaniu reguł zabezpieczeń, co pozwala funkcji wykonywać różne operacje w zależności od poziom uprawnień:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

Możesz też wykorzystać informacje uwierzytelniające użytkownika do „podszywania się pod inne osoby”. użytkownik i wykonywać operacje zapisu w imieniu użytkownika. Pamiętaj, aby usunąć instancji aplikacji, jak pokazano poniżej, aby uniknąć problemów z równoczesnością:

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

Odczyt poprzedniej wartości

Obiekt Change ma before pozwalającą sprawdzić, co zostało zapisane w Bazie danych czasu rzeczywistego, przed . Właściwość before zwraca wartość DataSnapshot, gdzie wszystkie (na przykład val() i exists()). odwołują się do poprzedniej wartości. Możesz ponownie odczytać nową wartość, używając zarówno argumentu oryginalny DataSnapshot lub czytając after usłudze. Ta usługa w dowolnym miejscu Change to inna usługa DataSnapshot reprezentująca wartość stan danych po wystąpieniu zdarzenia.

Na przykład przy użyciu właściwości before można upewnić się, że funkcja pisany jest wielkimi literami w chwili jego utworzenia:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return change.after.ref.parent.child('uppercase').set(uppercase);
    });