(İsteğe bağlı) Firebase Local Emulator Suite ile prototip oluşturma ve test etme
Uygulamanızın Realtime Database ile nasıl okuma ve yazma işlemi yaptığından bahsetmeden önce, Realtime Database işlevselliğini prototip oluşturmak ve test etmek için kullanabileceğiniz bir dizi aracı tanıtalım: Firebase Local Emulator Suite. Farklı veri modellerini deniyorsanız, güvenlik kurallarınızı optimize ediyorsanız veya arka uçla etkileşim kurmanın en uygun maliyetli yolunu bulmaya çalışıyorsanız canlı hizmetleri dağıtmadan yerel olarak çalışabilmek harika bir fikir olabilir.
Realtime Database emülatörü, Local Emulator Suite'nin bir parçasıdır. Bu araç, uygulamanızın emüle edilmiş veritabanı içeriğiniz ve yapılandırmanızla, ayrıca isteğe bağlı olarak emüle edilmiş proje kaynaklarınızla (işlevler, diğer veritabanları ve güvenlik kuralları) etkileşim kurmasını sağlar.
Realtime Database emülatörünü kullanmak için yalnızca birkaç adım gerekir:
- Emülatöre bağlanmak için uygulamanızın test yapılandırmasına bir kod satırı ekleyin.
- Yerel proje dizininizin kökünden
firebase emulators:start
komutunu çalıştırın. - Uygulamanızın prototip kodundan Realtime Database platform SDK'sını her zamanki gibi kullanarak veya Realtime Database REST API'yi kullanarak çağrı yapma.
Realtime Database ve Cloud Functions ile ilgili ayrıntılı birrehber mevcuttur. Ayrıca Local Emulator Suite giriş bölümüne de göz atmanız gerekir.
Veritabanı referansı alma
Veri tabanından veri okumak veya veri tabanına veri yazmak için firebase.database.Reference
örneğine ihtiyacınız vardır:
Web
import { getDatabase } from "firebase/database"; const database = getDatabase();
Web
var database = firebase.database();
Veri yazma
Bu belgede, verileri alma ve Firebase verilerini sıralama ve filtreleme ile ilgili temel bilgiler verilmektedir.
Firebase verileri, firebase.database.Reference
öğesine eşzamansız bir dinleyici eklenerek alınır. Dinleyici, verilerin ilk durumu için bir kez, veriler her değiştiğinde ise tekrar tetiklenir.
Temel yazma işlemleri
Temel yazma işlemleri için set()
kullanarak verileri belirtilen bir referansa kaydedebilir ve bu yoldaki mevcut verilerin yerini alabilirsiniz. Örneğin, sosyal blog uygulaması, set()
kullanıcılarını aşağıdaki gibi ekleyebilir:
Web
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
function writeUserData(userId, name, email, imageUrl) { firebase.database().ref('users/' + userId).set({ username: name, email: email, profile_picture : imageUrl }); }
set()
öğesini kullandığınızda, belirtilen konumdaki veriler (alt düğümler dahil) üzerine yazılır.
Verileri okuma
Değer etkinliklerini dinleme
Bir yoldaki verileri okumak ve değişiklikleri dinlemek için onValue()
kullanarak etkinlikleri gözlemleyin. Bu etkinliği, belirli bir yoldaki içeriklerin etkinliğin gerçekleştiği sıradaki statik anlık görüntülerini okumak için kullanabilirsiniz. Bu yöntem, dinleyici eklendiğinde bir kez, çocuklar dahil olmak üzere veriler her değiştiğinde ise tekrar tetiklenir. Etkinlik geri çağırmasına, alt veriler de dahil olmak üzere o konumdaki tüm verileri içeren bir anlık görüntü iletilir. Veri yoksa exists()
'ı aradığınızda anlık görüntü false
, val()
'ü aradığınızda ise null
değerini döndürür.
Aşağıdaki örnekte, bir gönderinin yıldız sayısını veritabanından alan bir sosyal blog uygulaması gösterilmektedir:
Web
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
var starCountRef = firebase.database().ref('posts/' + postId + '/starCount'); starCountRef.on('value', (snapshot) => { const data = snapshot.val(); updateStarCount(postElement, data); });
Dinleyici, etkinlik sırasında veritabanında belirtilen konumdaki verileri içeren bir snapshot
alır. snapshot
içindeki verileri val()
yöntemiyle alabilirsiniz.
Verileri bir kez okuma
get() ile verileri bir kez okuma
SDK, uygulamanızın çevrimiçi veya çevrimdışı olmasına bakılmaksızın veritabanı sunucularıyla etkileşimleri yönetmek için tasarlanmıştır.
Genel olarak, arka uçtaki verilerde yapılan güncellemelerden haberdar olmak için verileri okumak üzere yukarıda açıklanan değer etkinliği tekniklerini kullanmanız gerekir. Dinleyici teknikleri, kullanımınızı ve faturalandırmanızı azaltır. Ayrıca, kullanıcılarınıza çevrimiçi ve çevrimdışı olarak en iyi deneyimi sunmak için optimize edilmiştir.
Verilere yalnızca bir kez ihtiyacınız varsa veritabanındaki verilerin anlık görüntüsünü almak için get()
kullanabilirsiniz. get()
herhangi bir nedenle sunucu değerini döndüremiyorsa istemci, yerel depolama önbelleğini yoklar ve değer hâlâ bulunamazsa bir hata döndürür.
get()
öğesinin gereksiz kullanımı bant genişliği kullanımını artırabilir ve performans kaybına yol açabilir. Bu durum, yukarıda gösterildiği gibi gerçek zamanlı bir dinleyici kullanılarak önlenebilir.
Web
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
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); });
Verileri bir gözlemciyle bir kez okuma
Bazı durumlarda, sunucuda güncellenmiş bir değer olup olmadığını kontrol etmek yerine yerel önbellekteki değerin hemen döndürülmesini isteyebilirsiniz. Bu gibi durumlarda, yerel disk önbelleğindeki verileri hemen almak için once()
simgesini kullanabilirsiniz.
Bu, yalnızca bir kez yüklenmesi gereken ve sık sık değişmesi ya da aktif dinleme gerektirmesi beklenmeyen veriler için kullanışlıdır. Örneğin, önceki örneklerdeki blog uygulaması, kullanıcı yeni bir gönderi yazmaya başladığında profilini yüklemek için bu yöntemi kullanır:
Web
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
var userId = firebase.auth().currentUser.uid; return firebase.database().ref('/users/' + userId).once('value').then((snapshot) => { var username = (snapshot.val() && snapshot.val().username) || 'Anonymous'; // ... });
Verileri güncelleme veya silme
Belirli alanları güncelleme
Bir düğümün belirli alt öğelerine diğer alt düğümleri üzerine yazmadan aynı anda yazmak için update()
yöntemini kullanın.
update()
çağrısı yaparken anahtar için bir yol belirterek alt düzeydeki alt değerleri güncelleyebilirsiniz. Veriler daha iyi ölçeklendirme için birden fazla konumda depolanıyorsa veri dağıtımı kullanarak bu verilerin tüm örneklerini güncelleyebilirsiniz.
Örneğin, sosyal blog uygulaması aşağıdaki gibi bir kod kullanarak hem son etkinlik feed'inde hem de gönderiyi yayınlayan kullanıcının etkinlik feed'inde aynı anda bir gönderi oluşturup güncelleyebilir:
Web
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
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); }
Bu örnekte, push()
kullanılarak /posts/$postid
adresindeki tüm kullanıcıların yayınlarını içeren düğümde bir yayın oluşturulur ve aynı anda anahtar alınır. Anahtar daha sonra kullanıcının /user-posts/$userid/$postid
adresindeki yayınlarına ikinci bir giriş oluşturmak için kullanılabilir.
Bu yolları kullanarak, update()
için tek bir çağrıyla JSON ağacındaki birden fazla konumda eşzamanlı güncellemeler yapabilirsiniz. Örneğin, bu örnekte yeni gönderi her iki konumda da oluşturulur. Bu şekilde yapılan eşzamanlı güncellemeler atomiktir: Tüm güncellemeler başarılı olur veya tüm güncellemeler başarısız olur.
Tamamlama geri çağırması ekleme
Verilerinizin ne zaman işlendiğini öğrenmek istiyorsanız bir tamamlama geri araması ekleyebilirsiniz. Hem set()
hem de update()
, yazma işlemi veritabanına kaydedildiğinde çağrılan isteğe bağlı bir tamamlama geri çağırması alır. Arama başarısız olursa geri çağırma işlemine, hatanın nedenini belirten bir hata nesnesi iletilir.
Web
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
firebase.database().ref('users/' + userId).set({ username: name, email: email, profile_picture : imageUrl }, (error) => { if (error) { // The write failed... } else { // Data saved successfully! } });
Verileri silin
Verileri silmenin en basit yolu, verilerin konumuna yapılan bir referansta remove()
işlevini çağırmaktır.
Ayrıca null
veya update()
gibi başka bir yazma işlemi için değer olarak set()
belirterek de silebilirsiniz. Bu tekniği update()
ile birlikte kullanarak tek bir API çağrısında birden fazla alt öğeyi silebilirsiniz.
Promise
rozeti alma
Verilerinizin Firebase Realtime Database sunucusuna ne zaman işlendiğini öğrenmek için Promise
kullanabilirsiniz.
Hem set()
hem de update()
, yazma işleminin veritabanına ne zaman kaydedildiğini öğrenmek için kullanabileceğiniz bir Promise
döndürebilir.
Dinleyicileri ayırma
Geri aramalar, Firebase veritabanı referansınızda off()
yöntemi çağrılarak kaldırılır.
Tek bir dinleyiciyi off()
işlevine parametre olarak ileterek kaldırabilirsiniz.
Konumda bağımsız değişken olmadan off()
çağrısı yapıldığında, o konumdaki tüm dinleyiciler kaldırılır.
Bir ebeveyn dinleyicide off()
çağrısı yapılması, alt düğümlerinde kayıtlı dinleyicileri otomatik olarak kaldırmaz. Geri çağırmayı kaldırmak için tüm alt dinleyicilerde de off()
çağrısı yapılmalıdır.
Verileri işlem olarak kaydetme
Eşzamanlı değişiklikler nedeniyle bozulabilecek verilerle (ör. artımlı sayaçlar) çalışırken işlem işlemi kullanabilirsiniz. Bu işleme bir güncelleme işlevi ve isteğe bağlı bir tamamlama geri çağırması verebilirsiniz. Güncelleme işlevi, verilerin mevcut durumunu bağımsız değişken olarak alır ve yazmak istediğiniz yeni durumu döndürür. Başka bir istemci, yeni değeriniz başarıyla yazılmadan önce konuma yazarsa güncelleme işleviniz yeni geçerli değerle tekrar çağrılır ve yazma işlemi yeniden denenir.
Örneğin, örnek sosyal blog uygulamasında kullanıcıların gönderilere yıldız eklemesine ve yıldızları kaldırmasına izin verebilir, ayrıca bir gönderinin kaç yıldız aldığını aşağıdaki gibi takip edebilirsiniz:
Web
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
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; }); }
İşlem kullanmak, birden fazla kullanıcı aynı anda aynı gönderiye yıldız verirse veya istemcide eski veriler varsa yıldız sayılarının yanlış olmasını önler. İşlem reddedilirse sunucu, mevcut değeri istemciye döndürür. İstemci de işlemi güncellenmiş değerle tekrar çalıştırır. Bu işlem, işlem kabul edilene veya işlemi iptal edene kadar tekrarlanır.
Atomik sunucu tarafı artışları
Yukarıdaki kullanım alanında, veritabanına iki değer yazıyoruz: gönderiye yıldız ekleyen/kaldıran kullanıcının kimliği ve artırılmış yıldız sayısı. Kullanıcının yayını yıldızladığını zaten biliyorsak işlem yerine atomik artırma işlemi kullanabiliriz.
Web
function addStar(uid, key) { import { getDatabase, increment, ref, update } from "firebase/database"; const dbRef = ref(getDatabase()); const updates = {}; updates[`posts/${key}/stars/${uid}`] = true; updates[`posts/${key}/starCount`] = increment(1); updates[`user-posts/${key}/stars/${uid}`] = true; updates[`user-posts/${key}/starCount`] = increment(1); update(dbRef, updates); }
Web
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); }
Bu kodda işlem işlemi kullanılmadığı için çakışan bir güncelleme olduğunda otomatik olarak yeniden çalıştırılmaz. Ancak artırma işlemi doğrudan veritabanı sunucusunda gerçekleştiği için çakışma olasılığı yoktur.
Uygulamaya özgü çakışmaları (ör. kullanıcının daha önce yıldızladığı bir gönderiyi tekrar yıldızlaması) tespit edip reddetmek istiyorsanız bu kullanım alanı için özel güvenlik kuralları yazmanız gerekir.
Verilerle çevrimdışı çalışma
Bir istemcinin ağ bağlantısı kesilirse uygulamanız doğru şekilde çalışmaya devam eder.
Firebase veritabanına bağlı her istemci, etkin verilerin kendi dahili sürümünü korur. Veriler yazılırken önce bu yerel sürüme yazılır. Ardından Firebase istemcisi, bu verileri uzak veritabanı sunucularıyla ve diğer istemcilerle "en iyi çaba" prensibine göre senkronize eder.
Sonuç olarak, veritabanına yapılan tüm yazma işlemleri, sunucuya herhangi bir veri yazılmadan önce yerel etkinlikleri anında tetikler. Bu sayede uygulamanız, ağ gecikmesinden veya bağlantısından bağımsız olarak yanıt vermeye devam eder.
Bağlantı yeniden kurulduğunda uygulamanız, istemcinin mevcut sunucu durumuyla senkronize olması için uygun etkinlik kümesini alır. Bu işlem için özel kod yazmanız gerekmez.
Çevrimdışı davranış hakkında daha fazla bilgiyi Çevrimiçi ve çevrimdışı özellikler hakkında daha fazla bilgi başlıklı makalede bulabilirsiniz.