Pemicu Realtime Database

Dengan Cloud Functions, Anda dapat menangani peristiwa di Firebase Realtime Database tanpa harus memperbarui kode klien. Dengan Cloud Functions, Anda dapat menjalankan operasi database dengan hak istimewa administratif penuh dan memastikan setiap perubahan ke database diproses secara terpisah. Anda dapat melakukan perubahan pada Firebase Realtime Database melalui DataSnapshot atau Admin SDK.

Dalam siklus proses umum, fungsi Firebase Realtime Database melakukan hal-hal berikut:

  1. Menunggu perubahan pada lokasi database tertentu.
  2. Dipicu saat suatu peristiwa terjadi dan menjalankan tugasnya (lihat Apa yang dapat saya lakukan dengan Cloud Functions? untuk mengetahui contoh kasus penggunaan).
  3. Menerima objek data yang berisi snapshot data yang disimpan dalam dokumen yang ditentukan.

Memicu fungsi database

Buat fungsi baru untuk peristiwa Realtime Database dengan functions.database. Untuk mengontrol kapan fungsi terpicu, tentukan salah satu pengendali peristiwa dan tentukan lokasi database tempat peristiwa akan dideteksi.

Mengatur pengendali peristiwa

Dengan Functions, Anda dapat mengendalikan peristiwa database di dua tingkat kekhususan; Anda dapat memantau peristiwa pembuatan, pembaruan, atau penghapusan secara khusus, atau Anda dapat memantau perubahan apa pun ke lokasi. Cloud Functions mendukung pengendali peristiwa ini untuk Realtime Database:

  • onWrite(), terpicu saat data dibuat, diperbarui, atau dihapus di Realtime Database.
  • onCreate(), terpicu saat data baru dibuat di Realtime Database.
  • onUpdate(), terpicu saat data diperbarui di Realtime Database.
  • onDelete(), terpicu saat data dihapus dari Realtime Database.

Menentukan instance dan lokasi database

Untuk mengontrol kapan dan di mana fungsi akan dipicu, panggil ref(path) untuk menentukan lokasi, lalu tentukan instance database dengan instance('INSTANCE_NAME') jika Anda menginginkannya. Jika Anda tidak menentukan instance, fungsi tersebut akan menerapkan instance database default untuk project Firebase. Misalnya:

  • Instance database default: functions.database.ref('/foo/bar')
  • Instance bernama "my-app-db-2": functions.database.instance('my-app-db-2').ref('/foo/bar')

Metode ini akan mengarahkan fungsi Anda untuk menangani penulisan di lokasi tertentu dalam instance database. Spesifikasi lokasi mencocokkan semua penulisan yang ada di lokasi tertentu dan lokasi mana pun di bawahnya. Jika Anda menetapkan /foo/bar sebagai lokasi fungsi, peristiwa di kedua lokasi ini akan dicocokkan:

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

Bagaimanapun juga, Firebase menafsirkan bahwa peristiwa terjadi di /foo/bar, dan data peristiwa menyertakan data lama dan baru di /foo/bar. Jika data peristiwa kemungkinan berukuran besar, pertimbangkan untuk menggunakan beberapa fungsi di lokasi yang lebih dalam, bukan fungsi tunggal di dekat root database Anda. Untuk mendapatkan performa terbaik, hanya minta data di level sedalam mungkin.

Anda dapat menentukan komponen lokasi sebagai karakter pengganti dengan mengapitnya menggunakan kurung kurawal; ref('foo/{bar}') mencocokkan semua turunan /foo. Nilai komponen lokasi karakter pengganti ini tersedia dalam objek EventContext.params pada fungsi Anda. Dalam contoh ini, nilainya tersedia sebagai event.params.bar.

Lokasi dengan karakter pengganti dapat mencocokkan beberapa peristiwa dalam penulisan tunggal. Sisipan

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

mencocokkan lokasi "/foo/{bar}" dua kali: sekali dengan "hello": "world", lalu dengan "firebase": "functions".

Menangani data peristiwa

Saat menangani peristiwa Realtime Database, objek data yang ditampilkan adalah DataSnapshot. Untuk peristiwa onWrite atau onUpdate, parameter pertama adalah objek Change yang berisi dua snapshot yang mewakili status data sebelum dan setelah peristiwa pemicu. Untuk peristiwa onCreate dan onDelete, objek data yang ditampilkan adalah snapshot dari data yang dibuat atau dihapus.

Dalam contoh ini, fungsi mengambil snap sebagai snapshot untuk lokasi yang ditentukan, mengubah string di lokasi ini menjadi huruf kapital, dan menulis string yang telah diubah tersebut ke 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();
      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 snapshot.ref.parent.child('uppercase').set(uppercase);
    });

Mengakses informasi autentikasi pengguna

Dari EventContext.auth dan EventContext.authType, Anda dapat mengakses informasi pengguna, termasuk izin untuk pengguna yang memicu fungsi. Tindakan ini dapat berguna untuk memberlakukan aturan keamanan sehingga fungsi Anda dapat menyelesaikan operasi yang berlainan sesuai dengan tingkat izin pengguna:

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

Anda juga dapat memanfaatkan informasi autentikasi pengguna untuk "meniru identitas" pengguna dan melakukan operasi tulis atas nama pengguna tersebut. Pastikan untuk menghapus instance aplikasi seperti yang ditunjukkan di bawah ini untuk mencegah masalah konkurensi:

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

Membaca nilai sebelumnya

Objek Change memiliki properti before sehingga Anda dapat memeriksa data yang disimpan ke database sebelum peristiwa terjadi. Properti before akan menampilkan DataSnapshot, dengan semua metode (misalnya val() dan exists()) mengacu ke nilai sebelumnya. Anda dapat membaca kembali nilai baru ini menggunakan DataSnapshot asli atau membaca properti after. Properti ini pada setiap Change adalah DataSnapshot lain yang mewakili status data setelah peristiwa tersebut terjadi.

Misalnya, properti before dapat digunakan untuk memastikan bahwa fungsi hanya berupa teks huruf kapital ketika pertama kali dibuat:

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

Kirim masukan tentang...

Butuh bantuan? Kunjungi halaman dukungan kami.