Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Trigger del database in tempo reale

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Con Cloud Functions puoi gestire gli eventi nel database Firebase Realtime senza dover aggiornare il codice client. Cloud Functions ti consente di eseguire operazioni del database in tempo reale con privilegi amministrativi completi e garantisce che ogni modifica al database in tempo reale venga elaborata individualmente. Puoi apportare modifiche al database in tempo reale di Firebase tramite DataSnapshot o tramite Admin SDK .

In un ciclo di vita tipico, una funzione del database in tempo reale di Firebase esegue le seguenti operazioni:

  1. Attende le modifiche a una particolare posizione del database in tempo reale.
  2. Si attiva quando si verifica un evento ed esegue le sue attività (vedi Cosa posso fare con Cloud Functions? per esempi di casi d'uso).
  3. Riceve un oggetto dati che contiene un'istantanea dei dati archiviati nel documento specificato.

Attiva una funzione di database in tempo reale

Crea nuove funzioni per eventi di database in tempo reale con functions.database . Per controllare quando si attiva la funzione, specificare uno dei gestori di eventi e specificare il percorso del database in tempo reale in cui ascolterà gli eventi.

Imposta il gestore dell'evento

Le funzioni consentono di gestire gli eventi del database in tempo reale a due livelli di specificità; puoi ascoltare in modo specifico solo eventi di creazione, aggiornamento o eliminazione oppure puoi ascoltare qualsiasi modifica di qualsiasi tipo a un percorso. Cloud Functions supporta questi gestori di eventi per il database in tempo reale:

  • onWrite() , che si attiva quando i dati vengono creati, aggiornati o eliminati in Realtime Database.
  • onCreate() , che si attiva quando vengono creati nuovi dati nel database in tempo reale.
  • onUpdate() , che si attiva quando i dati vengono aggiornati nel database in tempo reale.
  • onDelete() , che si attiva quando i dati vengono eliminati dal database in tempo reale.

Specificare l'istanza e il percorso

Per controllare quando e dove deve essere attivata la tua funzione, chiama ref(path) per specificare un percorso e, facoltativamente, specifica un'istanza del database in tempo reale con instance('INSTANCE_NAME') . Se non specifichi un'istanza, la funzione viene distribuita nell'istanza del database in tempo reale predefinita per il progetto Firebase. Ad esempio:

  • Istanza del database in tempo reale predefinita: functions.database.ref('/foo/bar')
  • Istanza denominata "my-app-db-2": functions.database.instance('my-app-db-2').ref('/foo/bar')

Questi metodi indirizzano la tua funzione a gestire le scritture in un determinato percorso all'interno dell'istanza di Realtime Database. Le specifiche del percorso corrispondono a tutte le scritture che toccano un percorso, comprese le scritture che si verificano ovunque al di sotto di esso. Se imposti il ​​percorso per la tua funzione come /foo/bar , corrisponde agli eventi in entrambe queste posizioni:

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

In entrambi i casi, Firebase interpreta che l'evento si verifica in /foo/bar e i dati dell'evento includono i dati vecchi e nuovi in /foo/bar . Se i dati dell'evento potrebbero essere di grandi dimensioni, prendere in considerazione l'utilizzo di più funzioni in percorsi più profondi invece di una singola funzione vicino alla radice del database. Per ottenere le migliori prestazioni, richiedi solo i dati al livello più profondo possibile.

È possibile specificare un componente del percorso come carattere jolly racchiudendolo tra parentesi graffe; ref('foo/{bar}') corrisponde a qualsiasi figlio di /foo . I valori di questi componenti del percorso con caratteri jolly sono disponibili all'interno dell'oggetto EventContext.params della funzione. In questo esempio, il valore è disponibile come context.params.bar .

I percorsi con caratteri jolly possono corrispondere a più eventi da una singola scrittura. Un inserto di

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

corrisponde al percorso "/foo/{bar}" due volte: una volta con "hello": "world" e di nuovo con "firebase": "functions" .

Gestire i dati degli eventi

Quando si gestisce un evento di database in tempo reale, l'oggetto dati restituito è un DataSnapshot . Per gli eventi onWrite o onUpdate , il primo parametro è un oggetto Change che contiene due snapshot che rappresentano lo stato dei dati prima e dopo l'evento di attivazione. Per gli eventi onCreate e onDelete , l'oggetto dati restituito è uno snapshot dei dati creati o eliminati.

In questo esempio, la funzione recupera lo snapshot per il percorso specificato come snap , converte la stringa in quella posizione in maiuscolo e scrive la stringa modificata nel database:

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

Accesso alle informazioni di autenticazione dell'utente

Da EventContext.auth e EventContext.authType , puoi accedere alle informazioni sull'utente, incluse le autorizzazioni, per l'utente che ha attivato una funzione. Questo può essere utile per applicare le regole di sicurezza, consentendo alla tua funzione di completare diverse operazioni in base al livello di autorizzazioni dell'utente:

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

Inoltre, puoi sfruttare le informazioni di autenticazione dell'utente per "impersonare" un utente ed eseguire operazioni di scrittura per conto dell'utente. Assicurati di eliminare l'istanza dell'app come mostrato di seguito per evitare problemi di concorrenza:

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

Lettura del valore precedente

L'oggetto Change ha una proprietà before che ti consente di controllare cosa è stato salvato in Realtime Database prima dell'evento. La proprietà before restituisce un DataSnapshot in cui tutti i metodi (ad esempio val() ed exist exists() ) fanno riferimento al valore precedente. È possibile leggere nuovamente il nuovo valore utilizzando il DataSnapshot originale o leggendo la proprietà after . Questa proprietà su qualsiasi Change è un altro DataSnapshot che rappresenta lo stato dei dati dopo che si è verificato l'evento.

Ad esempio, la proprietà before può essere utilizzata per assicurarsi che la funzione metta solo in maiuscolo il testo quando viene creata per la prima volta:

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