Ikuti semua informasi yang diumumkan di Firebase Summit, dan pelajari bagaimana Firebase dapat membantu Anda mempercepat pengembangan aplikasi dan menjalankan aplikasi dengan percaya diri. Pelajari Lebih Lanjut

Membaca dan Menulis Data di Web

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

(Opsional) Membuat prototipe dan menguji dengan Firebase Local Emulator Suite

Sebelum berbicara tentang bagaimana aplikasi Anda membaca dari dan menulis ke Realtime Database, mari perkenalkan seperangkat alat yang dapat Anda gunakan untuk membuat prototipe dan menguji fungsionalitas Realtime Database: Firebase Local Emulator Suite. Jika Anda mencoba model data yang berbeda, mengoptimalkan aturan keamanan, atau berupaya menemukan cara yang paling hemat biaya untuk berinteraksi dengan back-end, dapat bekerja secara lokal tanpa menggunakan layanan langsung bisa menjadi ide bagus.

Emulator Realtime Database adalah bagian dari Local Emulator Suite, yang memungkinkan aplikasi Anda berinteraksi dengan konten dan konfigurasi database yang diemulasikan, serta secara opsional sumber daya proyek yang diemulasikan (fungsi, database lain, dan aturan keamanan).

Menggunakan emulator Realtime Database hanya memerlukan beberapa langkah:

  1. Menambahkan baris kode ke konfigurasi pengujian aplikasi Anda untuk terhubung ke emulator.
  2. Dari root direktori proyek lokal Anda, jalankan firebase emulators:start .
  3. Melakukan panggilan dari kode prototipe aplikasi Anda menggunakan SDK platform Realtime Database seperti biasa, atau menggunakan REST API Realtime Database.

Panduan mendetail yang melibatkan Realtime Database dan Cloud Functions tersedia. Anda juga harus melihat pengenalan Local Emulator Suite .

Dapatkan referensi basis data

Untuk membaca atau menulis data dari database, Anda memerlukan instance firebase.database.Reference :

Web version 9

import { getDatabase } from "firebase/database";

const database = getDatabase();

Web version 8

var database = firebase.database();

Menulis data

Dokumen ini membahas dasar-dasar pengambilan data serta cara mengurutkan dan memfilter data Firebase.

Data Firebase diambil dengan melampirkan pemroses asinkron ke firebase.database.Reference . Pemroses dipicu sekali untuk status awal data dan dipicu lagi setiap kali data berubah.

Operasi tulis dasar

Untuk operasi tulis dasar, Anda dapat menggunakan set() untuk menyimpan data ke referensi tertentu, menggantikan data yang ada di jalur tersebut. Misalnya aplikasi blog sosial dapat menambahkan pengguna dengan set() sebagai berikut:

Web version 9

import { getDatabase, ref, set } from "firebase/database";

function writeUserData(userId, name, email, imageUrl) {
  const db = getDatabase();
  set(ref(db, 'users/' + userId), {
    username: name,
    email: email,
    profile_picture : imageUrl
  });
}

Web version 8

function writeUserData(userId, name, email, imageUrl) {
  firebase.database().ref('users/' + userId).set({
    username: name,
    email: email,
    profile_picture : imageUrl
  });
}

Menggunakan set() menimpa data di lokasi yang ditentukan, termasuk simpul anak mana pun.

Membaca data

Dengarkan peristiwa nilai

Untuk membaca data di jalur dan memantau perubahan, gunakan onValue() untuk mengamati peristiwa. Anda dapat menggunakan kejadian ini untuk membaca cuplikan statis konten di jalur tertentu, seperti yang ada pada saat kejadian. Metode ini dipicu sekali saat pemroses dilampirkan dan dipicu lagi setiap kali data, termasuk turunan, berubah. Panggilan balik peristiwa diteruskan snapshot yang berisi semua data di lokasi itu, termasuk data anak. Jika tidak ada data, snapshot akan mengembalikan false saat Anda memanggil exists() dan null saat Anda memanggil val() padanya.

Contoh berikut menunjukkan aplikasi blogging sosial yang mengambil jumlah bintang sebuah postingan dari database:

Web version 9

import { getDatabase, ref, onValue} from "firebase/database";

const db = getDatabase();
const starCountRef = ref(db, 'posts/' + postId + '/starCount');
onValue(starCountRef, (snapshot) => {
  const data = snapshot.val();
  updateStarCount(postElement, data);
});

Web version 8

var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
starCountRef.on('value', (snapshot) => {
  const data = snapshot.val();
  updateStarCount(postElement, data);
});

Pendengar menerima snapshot yang berisi data di lokasi yang ditentukan dalam database pada saat kejadian. Anda dapat mengambil data dalam snapshot dengan metode val() .

Membaca data sekali

Baca data sekali dengan get()

SDK dirancang untuk mengelola interaksi dengan server database apakah aplikasi Anda sedang online atau offline.

Secara umum, Anda harus menggunakan teknik peristiwa nilai yang dijelaskan di atas untuk membaca data guna mendapatkan pemberitahuan tentang pembaruan data dari backend. Teknik pemroses mengurangi penggunaan dan penagihan Anda, dan dioptimalkan untuk memberikan pengalaman terbaik kepada pengguna Anda saat mereka online dan offline.

Jika Anda memerlukan data hanya sekali, Anda dapat menggunakan get() untuk mendapatkan cuplikan data dari database. Jika karena alasan apa pun get() tidak dapat mengembalikan nilai server, klien akan menyelidiki cache penyimpanan lokal dan mengembalikan kesalahan jika nilainya masih belum ditemukan.

Penggunaan get() yang tidak perlu dapat meningkatkan penggunaan bandwidth dan menyebabkan hilangnya kinerja, yang dapat dicegah dengan menggunakan pendengar waktu nyata seperti yang ditunjukkan di atas.

Web version 9

import { getDatabase, ref, child, get } from "firebase/database";

const dbRef = ref(getDatabase());
get(child(dbRef, `users/${userId}`)).then((snapshot) => {
  if (snapshot.exists()) {
    console.log(snapshot.val());
  } else {
    console.log("No data available");
  }
}).catch((error) => {
  console.error(error);
});

Web version 8

const dbRef = firebase.database().ref();
dbRef.child("users").child(userId).get().then((snapshot) => {
  if (snapshot.exists()) {
    console.log(snapshot.val());
  } else {
    console.log("No data available");
  }
}).catch((error) => {
  console.error(error);
});

Baca data sekali dengan pengamat

Dalam beberapa kasus, Anda mungkin ingin nilai dari cache lokal segera dikembalikan, alih-alih memeriksa nilai yang diperbarui di server. Dalam kasus tersebut, Anda dapat menggunakan once() untuk segera mendapatkan data dari cache disk lokal.

Ini berguna untuk data yang hanya perlu dimuat satu kali dan tidak diharapkan sering berubah atau memerlukan mendengarkan secara aktif. Misalnya, aplikasi blog pada contoh sebelumnya menggunakan metode ini untuk memuat profil pengguna saat mereka mulai membuat postingan baru:

Web version 9

import { getDatabase, ref, onValue } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const userId = auth.currentUser.uid;
return onValue(ref(db, '/users/' + userId), (snapshot) => {
  const username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
  // ...
}, {
  onlyOnce: true
});

Web version 8

var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).once('value').then((snapshot) => {
  var username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
  // ...
});

Memperbarui atau menghapus data

Perbarui bidang tertentu

Untuk secara bersamaan menulis ke node anak tertentu tanpa menimpa node anak lainnya, gunakan metode update() .

Saat memanggil update() , Anda bisa memperbarui nilai turunan tingkat rendah dengan menentukan jalur untuk kunci tersebut. Jika data disimpan di beberapa lokasi untuk menskalakan dengan lebih baik, Anda dapat memperbarui semua contoh data tersebut menggunakan data fan-out .

Misalnya, aplikasi blog sosial dapat membuat postingan dan secara bersamaan memperbaruinya ke umpan aktivitas terbaru dan umpan aktivitas pengguna postingan menggunakan kode seperti ini:

Web version 9

import { getDatabase, ref, child, push, update } from "firebase/database";

function writeNewPost(uid, username, picture, title, body) {
  const db = getDatabase();

  // A post entry.
  const postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  const newPostKey = push(child(ref(db), 'posts')).key;

  // Write the new post's data simultaneously in the posts list and the user's post list.
  const updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return update(ref(db), updates);
}

Web version 8

function writeNewPost(uid, username, picture, title, body) {
  // A post entry.
  var postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  var newPostKey = firebase.database().ref().child('posts').push().key;

  // Write the new post's data simultaneously in the posts list and the user's post list.
  var updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return firebase.database().ref().update(updates);
}

Contoh ini menggunakan push() untuk membuat postingan di node yang berisi postingan untuk semua pengguna di /posts/$postid dan sekaligus mengambil kuncinya. Kunci tersebut kemudian dapat digunakan untuk membuat entri kedua di postingan pengguna di /user-posts/$userid/$postid .

Dengan menggunakan jalur ini, Anda dapat melakukan pembaruan serentak ke beberapa lokasi di pohon JSON dengan satu panggilan ke update() , seperti bagaimana contoh ini membuat postingan baru di kedua lokasi. Pembaruan simultan yang dilakukan dengan cara ini bersifat atomik: semua pembaruan berhasil atau semua pembaruan gagal.

Tambahkan Callback Penyelesaian

Jika Anda ingin mengetahui kapan data Anda telah di-commit, Anda dapat menambahkan callback penyelesaian. Baik set() dan update() mengambil callback penyelesaian opsional yang dipanggil saat penulisan telah dilakukan ke database. Jika panggilan tidak berhasil, panggilan balik diteruskan objek kesalahan yang menunjukkan mengapa kegagalan terjadi.

Web version 9

import { getDatabase, ref, set } from "firebase/database";

const db = getDatabase();
set(ref(db, 'users/' + userId), {
  username: name,
  email: email,
  profile_picture : imageUrl
})
.then(() => {
  // Data saved successfully!
})
.catch((error) => {
  // The write failed...
});

Web version 8

firebase.database().ref('users/' + userId).set({
  username: name,
  email: email,
  profile_picture : imageUrl
}, (error) => {
  if (error) {
    // The write failed...
  } else {
    // Data saved successfully!
  }
});

Hapus data

Cara paling sederhana untuk menghapus data adalah dengan memanggil remove() pada referensi ke lokasi data tersebut.

Anda juga dapat menghapus dengan menentukan null sebagai nilai untuk operasi tulis lainnya seperti set() atau update() . Anda dapat menggunakan teknik ini dengan update() untuk menghapus banyak turunan dalam satu panggilan API.

Menerima Promise

Untuk mengetahui kapan data Anda di-commit ke server Firebase Realtime Database, Anda bisa menggunakan Promise . Baik set() maupun update() dapat mengembalikan Promise yang dapat Anda gunakan untuk mengetahui kapan penulisan dikomit ke database.

Pisahkan pendengar

Callback dihapus dengan memanggil metode off() pada referensi database Firebase Anda.

Anda dapat menghapus satu pendengar dengan mengirimkannya sebagai parameter ke off() . Memanggil off() di lokasi tanpa argumen akan menghapus semua pendengar di lokasi itu.

Memanggil off() pada pendengar induk tidak secara otomatis menghapus pendengar yang terdaftar pada node anaknya; off() juga harus dipanggil pada setiap anak pendengar untuk menghapus callback.

Simpan data sebagai transaksi

Saat bekerja dengan data yang dapat dirusak oleh modifikasi bersamaan, seperti penghitung inkremental, Anda dapat menggunakan operasi transaksi . Anda dapat memberikan operasi ini fungsi pembaruan dan callback penyelesaian opsional. Fungsi pembaruan mengambil keadaan data saat ini sebagai argumen dan mengembalikan keadaan baru yang diinginkan yang ingin Anda tulis. Jika klien lain menulis ke lokasi sebelum nilai baru Anda berhasil ditulis, fungsi pembaruan Anda dipanggil lagi dengan nilai baru saat ini, dan penulisan dicoba lagi.

Misalnya, dalam contoh aplikasi blog sosial, Anda dapat mengizinkan pengguna untuk memberi bintang dan menghapus postingan serta melacak jumlah bintang yang diterima postingan sebagai berikut:

Web version 9

import { getDatabase, ref, runTransaction } from "firebase/database";

function toggleStar(uid) {
  const db = getDatabase();
  const postRef = ref(db, '/posts/foo-bar-123');

  runTransaction(postRef, (post) => {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

Web version 8

function toggleStar(postRef, uid) {
  postRef.transaction((post) => {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

Menggunakan transaksi mencegah kesalahan jumlah bintang jika banyak pengguna membintangi posting yang sama pada waktu yang sama atau klien memiliki data basi. Jika transaksi ditolak, server mengembalikan nilai saat ini ke klien, yang menjalankan transaksi lagi dengan nilai yang diperbarui. Ini berulang sampai transaksi diterima atau Anda membatalkan transaksi.

Penambahan sisi server atomik

Dalam kasus penggunaan di atas, kami menulis dua nilai ke database: ID pengguna yang memberi bintang/menghapus bintang pada kiriman, dan jumlah bintang yang bertambah. Jika kita sudah mengetahui bahwa pengguna membintangi postingan tersebut, kita dapat menggunakan operasi peningkatan atom alih-alih transaksi.

function addStar(uid, key) {
  const updates = {};
  updates[`posts/${key}/stars/${uid}`] = true;
  updates[`posts/${key}/starCount`] = firebase.database.ServerValue.increment(1);
  updates[`user-posts/${key}/stars/${uid}`] = true;
  updates[`user-posts/${key}/starCount`] = firebase.database.ServerValue.increment(1);
  firebase.database().ref().update(updates);
}

Kode ini tidak menggunakan operasi transaksi, sehingga tidak dijalankan kembali secara otomatis jika ada pembaruan yang bertentangan. Namun, karena operasi penambahan terjadi langsung di server basis data, tidak ada kemungkinan konflik.

Jika Anda ingin mendeteksi dan menolak konflik khusus aplikasi, seperti pengguna yang membintangi kiriman yang telah mereka bintangi sebelumnya, Anda harus menulis aturan keamanan khusus untuk kasus penggunaan tersebut.

Bekerja dengan data luring

Jika klien kehilangan koneksi jaringannya, aplikasi Anda akan terus berfungsi dengan benar.

Setiap klien yang terhubung ke database Firebase mempertahankan versi internalnya sendiri dari setiap data aktif. Saat data ditulis, data ditulis ke versi lokal ini terlebih dahulu. Klien Firebase kemudian menyinkronkan data tersebut dengan server basis data jarak jauh dan dengan klien lain berdasarkan "upaya terbaik".

Akibatnya, semua penulisan ke database segera memicu peristiwa lokal, sebelum data apa pun ditulis ke server. Ini berarti aplikasi Anda tetap responsif terlepas dari latensi atau konektivitas jaringan.

Setelah konektivitas dibangun kembali, aplikasi Anda menerima rangkaian peristiwa yang sesuai sehingga klien menyinkronkan dengan status server saat ini, tanpa harus menulis kode khusus apa pun.

Kami akan berbicara lebih banyak tentang perilaku offline di Pelajari lebih lanjut tentang kemampuan online dan offline ..

Langkah selanjutnya

,

(Opsional) Membuat prototipe dan menguji dengan Firebase Local Emulator Suite

Sebelum berbicara tentang bagaimana aplikasi Anda membaca dari dan menulis ke Realtime Database, mari perkenalkan seperangkat alat yang dapat Anda gunakan untuk membuat prototipe dan menguji fungsionalitas Realtime Database: Firebase Local Emulator Suite. Jika Anda mencoba model data yang berbeda, mengoptimalkan aturan keamanan, atau berupaya menemukan cara yang paling hemat biaya untuk berinteraksi dengan back-end, dapat bekerja secara lokal tanpa menggunakan layanan langsung bisa menjadi ide bagus.

Emulator Realtime Database adalah bagian dari Local Emulator Suite, yang memungkinkan aplikasi Anda berinteraksi dengan konten dan konfigurasi database yang diemulasikan, serta secara opsional sumber daya proyek yang diemulasikan (fungsi, database lain, dan aturan keamanan).

Menggunakan emulator Realtime Database hanya memerlukan beberapa langkah:

  1. Menambahkan baris kode ke konfigurasi pengujian aplikasi Anda untuk terhubung ke emulator.
  2. Dari root direktori proyek lokal Anda, jalankan firebase emulators:start .
  3. Melakukan panggilan dari kode prototipe aplikasi Anda menggunakan SDK platform Realtime Database seperti biasa, atau menggunakan REST API Realtime Database.

Panduan mendetail yang melibatkan Realtime Database dan Cloud Functions tersedia. Anda juga harus melihat pengenalan Local Emulator Suite .

Dapatkan referensi basis data

Untuk membaca atau menulis data dari database, Anda memerlukan instance firebase.database.Reference :

Web version 9

import { getDatabase } from "firebase/database";

const database = getDatabase();

Web version 8

var database = firebase.database();

Menulis data

Dokumen ini membahas dasar-dasar pengambilan data serta cara mengurutkan dan memfilter data Firebase.

Data Firebase diambil dengan melampirkan pemroses asinkron ke firebase.database.Reference . Pemroses dipicu sekali untuk status awal data dan dipicu lagi setiap kali data berubah.

Operasi tulis dasar

Untuk operasi tulis dasar, Anda dapat menggunakan set() untuk menyimpan data ke referensi tertentu, menggantikan data yang ada di jalur tersebut. Misalnya aplikasi blog sosial dapat menambahkan pengguna dengan set() sebagai berikut:

Web version 9

import { getDatabase, ref, set } from "firebase/database";

function writeUserData(userId, name, email, imageUrl) {
  const db = getDatabase();
  set(ref(db, 'users/' + userId), {
    username: name,
    email: email,
    profile_picture : imageUrl
  });
}

Web version 8

function writeUserData(userId, name, email, imageUrl) {
  firebase.database().ref('users/' + userId).set({
    username: name,
    email: email,
    profile_picture : imageUrl
  });
}

Menggunakan set() menimpa data di lokasi yang ditentukan, termasuk simpul anak mana pun.

Membaca data

Dengarkan peristiwa nilai

Untuk membaca data di jalur dan memantau perubahan, gunakan onValue() untuk mengamati peristiwa. Anda dapat menggunakan kejadian ini untuk membaca cuplikan statis konten di jalur tertentu, seperti yang ada pada saat kejadian. Metode ini dipicu sekali saat pemroses dilampirkan dan dipicu lagi setiap kali data, termasuk turunan, berubah. Panggilan balik peristiwa diteruskan snapshot yang berisi semua data di lokasi itu, termasuk data anak. Jika tidak ada data, snapshot akan mengembalikan false saat Anda memanggil exists() dan null saat Anda memanggil val() padanya.

Contoh berikut menunjukkan aplikasi blogging sosial yang mengambil jumlah bintang sebuah postingan dari database:

Web version 9

import { getDatabase, ref, onValue} from "firebase/database";

const db = getDatabase();
const starCountRef = ref(db, 'posts/' + postId + '/starCount');
onValue(starCountRef, (snapshot) => {
  const data = snapshot.val();
  updateStarCount(postElement, data);
});

Web version 8

var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
starCountRef.on('value', (snapshot) => {
  const data = snapshot.val();
  updateStarCount(postElement, data);
});

Pendengar menerima snapshot yang berisi data di lokasi yang ditentukan dalam database pada saat kejadian. Anda dapat mengambil data dalam snapshot dengan metode val() .

Membaca data sekali

Baca data sekali dengan get()

SDK dirancang untuk mengelola interaksi dengan server database apakah aplikasi Anda sedang online atau offline.

Secara umum, Anda harus menggunakan teknik peristiwa nilai yang dijelaskan di atas untuk membaca data guna mendapatkan pemberitahuan tentang pembaruan data dari backend. Teknik pemroses mengurangi penggunaan dan penagihan Anda, dan dioptimalkan untuk memberikan pengalaman terbaik kepada pengguna Anda saat mereka online dan offline.

Jika Anda memerlukan data hanya sekali, Anda dapat menggunakan get() untuk mendapatkan cuplikan data dari database. Jika karena alasan apa pun get() tidak dapat mengembalikan nilai server, klien akan menyelidiki cache penyimpanan lokal dan mengembalikan kesalahan jika nilainya masih belum ditemukan.

Penggunaan get() yang tidak perlu dapat meningkatkan penggunaan bandwidth dan menyebabkan hilangnya kinerja, yang dapat dicegah dengan menggunakan pendengar waktu nyata seperti yang ditunjukkan di atas.

Web version 9

import { getDatabase, ref, child, get } from "firebase/database";

const dbRef = ref(getDatabase());
get(child(dbRef, `users/${userId}`)).then((snapshot) => {
  if (snapshot.exists()) {
    console.log(snapshot.val());
  } else {
    console.log("No data available");
  }
}).catch((error) => {
  console.error(error);
});

Web version 8

const dbRef = firebase.database().ref();
dbRef.child("users").child(userId).get().then((snapshot) => {
  if (snapshot.exists()) {
    console.log(snapshot.val());
  } else {
    console.log("No data available");
  }
}).catch((error) => {
  console.error(error);
});

Baca data sekali dengan pengamat

Dalam beberapa kasus, Anda mungkin ingin nilai dari cache lokal segera dikembalikan, alih-alih memeriksa nilai yang diperbarui di server. Dalam kasus tersebut, Anda dapat menggunakan once() untuk segera mendapatkan data dari cache disk lokal.

Ini berguna untuk data yang hanya perlu dimuat satu kali dan tidak diharapkan sering berubah atau memerlukan mendengarkan secara aktif. Misalnya, aplikasi blog pada contoh sebelumnya menggunakan metode ini untuk memuat profil pengguna saat mereka mulai membuat postingan baru:

Web version 9

import { getDatabase, ref, onValue } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const userId = auth.currentUser.uid;
return onValue(ref(db, '/users/' + userId), (snapshot) => {
  const username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
  // ...
}, {
  onlyOnce: true
});

Web version 8

var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).once('value').then((snapshot) => {
  var username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
  // ...
});

Memperbarui atau menghapus data

Perbarui bidang tertentu

Untuk secara bersamaan menulis ke node anak tertentu tanpa menimpa node anak lainnya, gunakan metode update() .

Saat memanggil update() , Anda bisa memperbarui nilai turunan tingkat rendah dengan menentukan jalur untuk kunci tersebut. Jika data disimpan di beberapa lokasi untuk menskalakan dengan lebih baik, Anda dapat memperbarui semua contoh data tersebut menggunakan data fan-out .

Misalnya, aplikasi blog sosial dapat membuat postingan dan secara bersamaan memperbaruinya ke umpan aktivitas terbaru dan umpan aktivitas pengguna postingan menggunakan kode seperti ini:

Web version 9

import { getDatabase, ref, child, push, update } from "firebase/database";

function writeNewPost(uid, username, picture, title, body) {
  const db = getDatabase();

  // A post entry.
  const postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  const newPostKey = push(child(ref(db), 'posts')).key;

  // Write the new post's data simultaneously in the posts list and the user's post list.
  const updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return update(ref(db), updates);
}

Web version 8

function writeNewPost(uid, username, picture, title, body) {
  // A post entry.
  var postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  var newPostKey = firebase.database().ref().child('posts').push().key;

  // Write the new post's data simultaneously in the posts list and the user's post list.
  var updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return firebase.database().ref().update(updates);
}

Contoh ini menggunakan push() untuk membuat postingan di node yang berisi postingan untuk semua pengguna di /posts/$postid dan sekaligus mengambil kuncinya. Kunci tersebut kemudian dapat digunakan untuk membuat entri kedua di postingan pengguna di /user-posts/$userid/$postid .

Dengan menggunakan jalur ini, Anda dapat melakukan pembaruan serentak ke beberapa lokasi di pohon JSON dengan satu panggilan ke update() , seperti bagaimana contoh ini membuat postingan baru di kedua lokasi. Pembaruan simultan yang dilakukan dengan cara ini bersifat atomik: semua pembaruan berhasil atau semua pembaruan gagal.

Tambahkan Callback Penyelesaian

Jika Anda ingin mengetahui kapan data Anda telah di-commit, Anda dapat menambahkan callback penyelesaian. Baik set() dan update() mengambil callback penyelesaian opsional yang dipanggil saat penulisan telah dilakukan ke database. Jika panggilan tidak berhasil, panggilan balik diteruskan objek kesalahan yang menunjukkan mengapa kegagalan terjadi.

Web version 9

import { getDatabase, ref, set } from "firebase/database";

const db = getDatabase();
set(ref(db, 'users/' + userId), {
  username: name,
  email: email,
  profile_picture : imageUrl
})
.then(() => {
  // Data saved successfully!
})
.catch((error) => {
  // The write failed...
});

Web version 8

firebase.database().ref('users/' + userId).set({
  username: name,
  email: email,
  profile_picture : imageUrl
}, (error) => {
  if (error) {
    // The write failed...
  } else {
    // Data saved successfully!
  }
});

Hapus data

Cara paling sederhana untuk menghapus data adalah dengan memanggil remove() pada referensi ke lokasi data tersebut.

Anda juga dapat menghapus dengan menentukan null sebagai nilai untuk operasi tulis lainnya seperti set() atau update() . Anda dapat menggunakan teknik ini dengan update() untuk menghapus banyak turunan dalam satu panggilan API.

Menerima Promise

Untuk mengetahui kapan data Anda di-commit ke server Firebase Realtime Database, Anda bisa menggunakan Promise . Baik set() maupun update() dapat mengembalikan Promise yang dapat Anda gunakan untuk mengetahui kapan penulisan dikomit ke database.

Pisahkan pendengar

Callback dihapus dengan memanggil metode off() pada referensi database Firebase Anda.

Anda dapat menghapus satu pendengar dengan mengirimkannya sebagai parameter ke off() . Memanggil off() di lokasi tanpa argumen akan menghapus semua pendengar di lokasi itu.

Memanggil off() pada pendengar induk tidak secara otomatis menghapus pendengar yang terdaftar pada node anaknya; off() juga harus dipanggil pada setiap anak pendengar untuk menghapus callback.

Simpan data sebagai transaksi

Saat bekerja dengan data yang dapat dirusak oleh modifikasi bersamaan, seperti penghitung inkremental, Anda dapat menggunakan operasi transaksi . Anda dapat memberikan operasi ini fungsi pembaruan dan callback penyelesaian opsional. Fungsi pembaruan mengambil keadaan data saat ini sebagai argumen dan mengembalikan keadaan baru yang diinginkan yang ingin Anda tulis. Jika klien lain menulis ke lokasi sebelum nilai baru Anda berhasil ditulis, fungsi pembaruan Anda dipanggil lagi dengan nilai baru saat ini, dan penulisan dicoba lagi.

Misalnya, dalam contoh aplikasi blog sosial, Anda dapat mengizinkan pengguna untuk memberi bintang dan menghapus postingan serta melacak jumlah bintang yang diterima postingan sebagai berikut:

Web version 9

import { getDatabase, ref, runTransaction } from "firebase/database";

function toggleStar(uid) {
  const db = getDatabase();
  const postRef = ref(db, '/posts/foo-bar-123');

  runTransaction(postRef, (post) => {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

Web version 8

function toggleStar(postRef, uid) {
  postRef.transaction((post) => {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

Menggunakan transaksi mencegah kesalahan jumlah bintang jika banyak pengguna membintangi posting yang sama pada waktu yang sama atau klien memiliki data basi. Jika transaksi ditolak, server mengembalikan nilai saat ini ke klien, yang menjalankan transaksi lagi dengan nilai yang diperbarui. Ini berulang sampai transaksi diterima atau Anda membatalkan transaksi.

Penambahan sisi server atomik

Dalam kasus penggunaan di atas, kami menulis dua nilai ke database: ID pengguna yang memberi bintang/menghapus bintang pada kiriman, dan jumlah bintang yang bertambah. Jika kita sudah mengetahui bahwa pengguna membintangi postingan tersebut, kita dapat menggunakan operasi peningkatan atom alih-alih transaksi.

function addStar(uid, key) {
  const updates = {};
  updates[`posts/${key}/stars/${uid}`] = true;
  updates[`posts/${key}/starCount`] = firebase.database.ServerValue.increment(1);
  updates[`user-posts/${key}/stars/${uid}`] = true;
  updates[`user-posts/${key}/starCount`] = firebase.database.ServerValue.increment(1);
  firebase.database().ref().update(updates);
}

Kode ini tidak menggunakan operasi transaksi, sehingga tidak dijalankan kembali secara otomatis jika ada pembaruan yang bertentangan. Namun, karena operasi penambahan terjadi langsung di server basis data, tidak ada kemungkinan konflik.

Jika Anda ingin mendeteksi dan menolak konflik khusus aplikasi, seperti pengguna yang membintangi kiriman yang telah mereka bintangi sebelumnya, Anda harus menulis aturan keamanan khusus untuk kasus penggunaan tersebut.

Bekerja dengan data luring

Jika klien kehilangan koneksi jaringannya, aplikasi Anda akan terus berfungsi dengan benar.

Setiap klien yang terhubung ke database Firebase mempertahankan versi internalnya sendiri dari setiap data aktif. Saat data ditulis, data ditulis ke versi lokal ini terlebih dahulu. Klien Firebase kemudian menyinkronkan data tersebut dengan server basis data jarak jauh dan dengan klien lain berdasarkan "upaya terbaik".

Akibatnya, semua penulisan ke database segera memicu peristiwa lokal, sebelum data apa pun ditulis ke server. Ini berarti aplikasi Anda tetap responsif terlepas dari latensi atau konektivitas jaringan.

Setelah konektivitas dibangun kembali, aplikasi Anda menerima rangkaian peristiwa yang sesuai sehingga klien menyinkronkan dengan status server saat ini, tanpa harus menulis kode khusus apa pun.

Kami akan berbicara lebih banyak tentang perilaku offline di Pelajari lebih lanjut tentang kemampuan online dan offline ..

Langkah selanjutnya