(ज़रूरी नहीं) Firebase Local Emulator Suite की मदद से प्रोटोटाइप बनाना और उसकी जांच करना
आपका ऐप्लिकेशन, Realtime Database से डेटा कैसे पढ़ता है और उसमें डेटा कैसे सेव करता है, इस बारे में बात करने से पहले, आइए हम आपको टूल के एक सेट के बारे में बताते हैं. इसका इस्तेमाल करके, Realtime Database की सुविधाओं का प्रोटोटाइप बनाया जा सकता है और उन्हें टेस्ट किया जा सकता है: Firebase Local Emulator Suite. अगर आपको अलग-अलग डेटा मॉडल आज़माने हैं, सुरक्षा नियमों को ऑप्टिमाइज़ करना है या बैक-एंड के साथ इंटरैक्ट करने का सबसे किफ़ायती तरीका ढूंढना है, तो लाइव सेवाओं को डिप्लॉय किए बिना स्थानीय तौर पर काम करना एक अच्छा आइडिया हो सकता है.
Realtime Database एम्युलेटर, Local Emulator Suite का हिस्सा है. इसकी मदद से, आपका ऐप्लिकेशन आपके एम्युलेट किए गए डेटाबेस कॉन्टेंट और कॉन्फ़िगरेशन के साथ इंटरैक्ट कर सकता है. साथ ही, आपके एम्युलेट किए गए प्रोजेक्ट रिसॉर्स (फ़ंक्शन, अन्य डेटाबेस, और सुरक्षा के नियम) के साथ भी इंटरैक्ट कर सकता है.
Realtime Database एम्युलेटर का इस्तेमाल करने के लिए, बस कुछ ही चरणों को पूरा करना होता है:
- एम्युलेटर से कनेक्ट करने के लिए, अपने ऐप्लिकेशन के टेस्ट कॉन्फ़िगरेशन में कोड की एक लाइन जोड़ना.
- अपनी लोकल प्रोजेक्ट डायरेक्ट्री के रूट से,
firebase emulators:startचलाएं. - Realtime Database प्लैटफ़ॉर्म के एसडीके टूल का इस्तेमाल करके, अपने ऐप्लिकेशन के प्रोटोटाइप कोड से कॉल करना या Realtime Database REST API का इस्तेमाल करना.
Realtime Database और Cloud Functions के बारे में ज़्यादा जानकारी देने वाला वॉकथ्रू उपलब्ध है. आपको Local Emulator Suite के बारे में जानकारी भी देखनी चाहिए.
FIRDatabaseReference पाना
डेटाबेस से डेटा पढ़ने या उसमें डेटा लिखने के लिए, आपको FIRDatabaseReference के इंस्टेंस की ज़रूरत होगी:
Swift
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
डेटा सेव करने की अनुमति दें
इस दस्तावेज़ में, Firebase डेटा को पढ़ने और लिखने से जुड़ी बुनियादी जानकारी दी गई है.
Firebase डेटा को Database रेफ़रंस में लिखा जाता है. साथ ही, रेफ़रंस में एसिंक्रोनस लिसनर को अटैच करके, डेटा को वापस पाया जाता है. लिसनर को डेटा की शुरुआती स्थिति के लिए एक बार ट्रिगर किया जाता है. इसके बाद, डेटा में बदलाव होने पर इसे फिर से ट्रिगर किया जाता है.
डेटा में बदलाव करने की बुनियादी कार्रवाइयां
डेटा को सेव करने के लिए, setValue का इस्तेमाल किया जा सकता है. इससे डेटा, दिए गए रेफ़रंस में सेव हो जाता है और उस पाथ पर मौजूद मौजूदा डेटा को बदल देता है. इस तरीके का इस्तेमाल करके:
- पास के टाइप, जो उपलब्ध JSON टाइप से मेल खाते हैं:
NSStringNSNumberNSDictionaryNSArray
उदाहरण के लिए, setValue का इस्तेमाल करके किसी उपयोगकर्ता को इस तरह जोड़ा जा सकता है:
Swift
self.ref.child("users").child(user.uid).setValue(["username": username])
Objective-C
[[[self.ref child:@"users"] child:authResult.user.uid] setValue:@{@"username": username}];
इस तरह से setValue का इस्तेमाल करने पर, तय की गई जगह पर मौजूद डेटा को ओवरराइट कर दिया जाता है. इसमें सभी चाइल्ड नोड भी शामिल हैं. हालांकि, पूरे ऑब्जेक्ट को फिर से लिखे बिना भी चाइल्ड को अपडेट किया जा सकता है. अगर आपको उपयोगकर्ताओं को अपनी प्रोफ़ाइल अपडेट करने की अनुमति देनी है, तो उपयोगकर्ता नाम को इस तरह अपडेट किया जा सकता है:
Swift
self.ref.child("users/\(user.uid)/username").setValue(username)
Objective-C
[[[[_ref child:@"users"] child:user.uid] child:@"username"] setValue:username];
डेटा पढ़ने की अनुमति दें
वैल्यू इवेंट को मॉनिटर करके डेटा पढ़ना
किसी पाथ पर मौजूद डेटा को पढ़ने और उसमें होने वाले बदलावों पर नज़र रखने के लिए, FIRDatabaseReference के observeEventType:withBlock का इस्तेमाल करें. इससे FIRDataEventTypeValue इवेंट पर नज़र रखी जा सकती है.
| इवेंट प्रकार | आम तौर पर इस्तेमाल |
|---|---|
FIRDataEventTypeValue |
किसी पाथ के पूरे कॉन्टेंट में होने वाले बदलावों को पढ़ना और सुनना. |
FIRDataEventTypeValue इवेंट का इस्तेमाल करके, किसी पाथ पर मौजूद डेटा को पढ़ा जा सकता है. यह डेटा, इवेंट के समय मौजूद होता है. यह तरीका, लिसनर के अटैच होने पर एक बार ट्रिगर होता है. इसके बाद, डेटा में बदलाव होने पर यह हर बार ट्रिगर होता है. इसमें चाइल्ड डेटा भी शामिल है. इवेंट कॉलबैक को एक snapshot पास किया जाता है. इसमें उस जगह का पूरा डेटा होता है. इसमें चाइल्ड डेटा भी शामिल होता है. अगर कोई डेटा मौजूद नहीं है, तो exists() को कॉल करने पर स्नैपशॉट false दिखाएगा. साथ ही, इसकी value प्रॉपर्टी को पढ़ने पर nil दिखाएगा.
यहां दिए गए उदाहरण में, सोशल ब्लॉगिंग ऐप्लिकेशन को डेटाबेस से किसी पोस्ट की जानकारी को वापस पाने का तरीका दिखाया गया है:
Swift
refHandle = postRef.observe(DataEventType.value, with: { snapshot in // ... })
Objective-C
_refHandle = [_postRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { NSDictionary *postDict = snapshot.value; // ... }];
लिसनर को एक FIRDataSnapshot मिलता है. इसमें डेटाबेस में तय की गई जगह पर मौजूद डेटा होता है. यह डेटा, इवेंट के समय उसकी value प्रॉपर्टी में मौजूद होता है. वैल्यू को सही नेटिव टाइप में असाइन किया जा सकता है, जैसे कि NSDictionary.
अगर उस जगह पर कोई डेटा मौजूद नहीं है, तो value nil है.
एक बार डेटा पढ़ने की अनुमति दें
getData() का इस्तेमाल करके एक बार पढ़ना
इस एसडीके को डेटाबेस सर्वर के साथ इंटरैक्शन मैनेज करने के लिए डिज़ाइन किया गया है. इससे कोई फ़र्क़ नहीं पड़ता कि आपका ऐप्लिकेशन ऑनलाइन है या ऑफ़लाइन.
आम तौर पर, आपको डेटा पढ़ने के लिए, ऊपर बताई गई वैल्यू इवेंट की तकनीकों का इस्तेमाल करना चाहिए. इससे आपको बैकएंड से डेटा के अपडेट की सूचना मिलेगी. इन तकनीकों से, आपके इस्तेमाल और बिलिंग में कमी आती है. साथ ही, इन्हें इस तरह से ऑप्टिमाइज़ किया जाता है कि आपके उपयोगकर्ताओं को ऑनलाइन और ऑफ़लाइन होने पर सबसे अच्छा अनुभव मिले.
अगर आपको डेटा सिर्फ़ एक बार चाहिए, तो डेटाबेस से डेटा का स्नैपशॉट पाने के लिए, getData() का इस्तेमाल करें. अगर किसी वजह से getData(), सर्वर की वैल्यू नहीं दिखा पाता है, तो क्लाइंट लोकल स्टोरेज कैश मेमोरी की जांच करेगा. अगर वैल्यू अब भी नहीं मिलती है, तो गड़बड़ी का मैसेज दिखाएगा.
इस उदाहरण में, डेटाबेस से उपयोगकर्ता का सार्वजनिक तौर पर दिखने वाला उपयोगकर्ता नाम एक बार वापस पाने का तरीका बताया गया है:
Swift
do { let snapshot = try await ref.child("users/\(uid)/username").getData() let userName = snapshot.value as? String ?? "Unknown" } catch { print(error) }
Objective-C
NSString *userPath = [NSString stringWithFormat:@"users/%@/username", uid]; [[ref child:userPath] getDataWithCompletionBlock:^(NSError * _Nullable error, FIRDataSnapshot * _Nonnull snapshot) { if (error) { NSLog(@"Received an error %@", error); return; } NSString *userName = snapshot.value; }];
getData() का बेवजह इस्तेमाल करने से, बैंडविड्थ का इस्तेमाल बढ़ सकता है. साथ ही, परफ़ॉर्मेंस में गिरावट आ सकती है. इसे रोकने के लिए, रीयलटाइम लिसनर का इस्तेमाल किया जा सकता है, जैसा कि ऊपर दिखाया गया है.
ऑब्ज़र्वर की मदद से डेटा को एक बार पढ़ना
कुछ मामलों में, हो सकता है कि आपको सर्वर पर अपडेट की गई वैल्यू देखने के बजाय, लोकल कैश मेमोरी से वैल्यू तुरंत वापस चाहिए. ऐसे मामलों में, observeSingleEventOfType का इस्तेमाल करके, लोकल डिस्क की कैश मेमोरी से डेटा तुरंत हासिल किया जा सकता है.
यह ऐसे डेटा के लिए मददगार है जिसे सिर्फ़ एक बार लोड करना होता है और जिसमें बार-बार बदलाव होने की उम्मीद नहीं होती या जिसे लगातार सुनने की ज़रूरत नहीं होती. उदाहरण के लिए, पिछले उदाहरणों में मौजूद ब्लॉगिंग ऐप्लिकेशन, इस तरीके का इस्तेमाल करके उपयोगकर्ता की प्रोफ़ाइल लोड करता है. ऐसा तब होता है, जब उपयोगकर्ता कोई नई पोस्ट लिखना शुरू करता है:
Swift
let userID = Auth.auth().currentUser?.uid ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { snapshot in // Get user value let value = snapshot.value as? NSDictionary let username = value?["username"] as? String ?? "" let user = User(username: username) // ... }) { error in print(error.localizedDescription) }
Objective-C
NSString *userID = [FIRAuth auth].currentUser.uid; [[[_ref child:@"users"] child:userID] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { // Get user value User *user = [[User alloc] initWithUsername:snapshot.value[@"username"]]; // ... } withCancelBlock:^(NSError * _Nonnull error) { NSLog(@"%@", error.localizedDescription); }];
डेटा अपडेट करना या मिटाना
चुनिंदा फ़ील्ड अपडेट करना
किसी नोड के कुछ चाइल्ड नोड में एक साथ डेटा लिखने के लिए, updateChildValues तरीके का इस्तेमाल करें. इससे अन्य चाइल्ड नोड का डेटा ओवरराइट नहीं होता.
updateChildValues को कॉल करते समय, कुंजी के लिए पाथ तय करके, निचले लेवल की चाइल्ड वैल्यू को अपडेट किया जा सकता है. अगर डेटा को बेहतर तरीके से स्केल करने के लिए कई जगहों पर सेव किया गया है, तो डेटा फ़ैन-आउट का इस्तेमाल करके, उस डेटा के सभी इंस्टेंस अपडेट किए जा सकते हैं. उदाहरण के लिए, कोई सोशल ब्लॉगिंग ऐप्लिकेशन, पोस्ट बनाने के साथ-साथ उसे हाल ही की गतिविधि फ़ीड और पोस्ट करने वाले उपयोगकर्ता की गतिविधि फ़ीड में अपडेट करना चाहता है. इसके लिए, ब्लॉगिंग ऐप्लिकेशन
इस तरह के कोड का इस्तेमाल करता है:
Swift
guard let key = ref.child("posts").childByAutoId().key else { return } let post = ["uid": userID, "author": username, "title": title, "body": body] let childUpdates = ["/posts/\(key)": post, "/user-posts/\(userID)/\(key)/": post] ref.updateChildValues(childUpdates)
Objective-C
NSString *key = [[_ref child:@"posts"] childByAutoId].key; NSDictionary *post = @{@"uid": userID, @"author": username, @"title": title, @"body": body}; NSDictionary *childUpdates = @{[@"/posts/" stringByAppendingString:key]: post, [NSString stringWithFormat:@"/user-posts/%@/%@/", userID, key]: post}; [_ref updateChildValues:childUpdates];
इस उदाहरण में, childByAutoId का इस्तेमाल करके उस नोड में पोस्ट बनाई गई है जिसमें /posts/$postid पर मौजूद सभी उपयोगकर्ताओं की पोस्ट शामिल हैं. साथ ही, getKey() का इस्तेमाल करके कुंजी को वापस लाया गया है. इसके बाद, इस कुंजी का इस्तेमाल करके, /user-posts/$userid/$postid पर उपयोगकर्ता की पोस्ट में दूसरी एंट्री बनाई जा सकती है.
इन पाथ का इस्तेमाल करके, JSON ट्री में मौजूद कई जगहों को एक साथ अपडेट किया जा सकता है. इसके लिए, updateChildValues को एक बार कॉल करना होगा. उदाहरण के लिए, इस उदाहरण में दोनों जगहों पर नई पोस्ट बनाई गई है. इस तरह से एक साथ किए गए अपडेट,
ऐटॉमिक होते हैं: या तो सभी अपडेट सफल होते हैं या सभी अपडेट फ़ेल हो जाते हैं.
पूरा होने की जानकारी देने वाला ब्लॉक जोड़ना
अगर आपको यह जानना है कि आपका डेटा कब कमिट किया गया है, तो आपके पास पूरा होने का ब्लॉक जोड़ने का विकल्प है. setValue और updateChildValues, दोनों में एक वैकल्पिक कंप्लीशन ब्लॉक होता है. इसे तब कॉल किया जाता है, जब डेटाबेस में डेटा सेव हो जाता है. इस लिसनर का इस्तेमाल करके, यह ट्रैक किया जा सकता है कि कौनसा डेटा सेव किया गया है और कौनसा डेटा अब भी सिंक किया जा रहा है. अगर कॉल पूरा नहीं हो पाता है, तो लिसनर को गड़बड़ी का ऑब्जेक्ट पास किया जाता है. इससे पता चलता है कि गड़बड़ी क्यों हुई.
Swift
do { try await ref.child("users").child(user.uid).setValue(["username": username]) print("Data saved successfully!") } catch { print("Data could not be saved: \(error).") }
Objective-C
[[[_ref child:@"users"] child:user.uid] setValue:@{@"username": username} withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) { if (error) { NSLog(@"Data could not be saved: %@", error); } else { NSLog(@"Data saved successfully."); } }];
डाटा हटाएं
डेटा मिटाने का सबसे आसान तरीका है कि उस डेटा की जगह के रेफ़रंस पर removeValue को कॉल करें.
nil को किसी अन्य राइट ऑपरेशन, जैसे कि setValue या updateChildValues की वैल्यू के तौर पर तय करके भी मिटाया जा सकता है. एक ही एपीआई कॉल में कई चाइल्ड प्रॉपर्टी मिटाने के लिए, updateChildValues के साथ इस तकनीक का इस्तेमाल किया जा सकता है.
लिसनर को अलग करना
ViewController छोड़ने पर, ऑब्ज़र्वर डेटा को सिंक करना अपने-आप बंद नहीं करते. अगर किसी ऑब्ज़र्वर को सही तरीके से नहीं हटाया जाता है, तो वह लोकल मेमोरी में डेटा सिंक करता रहता है. जब ऑब्ज़र्वर की ज़रूरत न हो, तो उससे जुड़े FIRDatabaseHandle को removeObserverWithHandle तरीके में पास करके उसे हटा दें.
किसी रेफ़रंस में कॉलबैक ब्लॉक जोड़ने पर, FIRDatabaseHandle मिलता है.
इन हैंडल का इस्तेमाल करके, कॉलबैक ब्लॉक को हटाया जा सकता है.
अगर किसी डेटाबेस रेफ़रंस में कई लिसनर जोड़े गए हैं, तो कोई इवेंट होने पर हर लिसनर को कॉल किया जाता है. उस जगह पर डेटा सिंक करना बंद करने के लिए, आपको removeAllObservers तरीके को कॉल करके, उस जगह पर मौजूद सभी ऑब्ज़र्वर को हटाना होगा.
किसी लिसनर पर removeObserverWithHandle या removeAllObservers को कॉल करने से, उसके चाइल्ड नोड पर रजिस्टर किए गए लिसनर अपने-आप नहीं हटते. आपको उन रेफ़रंस या हैंडल को हटाने के लिए, उन्हें ट्रैक करना होगा.
डेटा को लेन-देन के तौर पर सेव करना
जब ऐसे डेटा के साथ काम किया जा रहा हो जो एक साथ किए गए बदलावों की वजह से खराब हो सकता है, जैसे कि बढ़ने वाले काउंटर, तो ट्रांज़ैक्शन ऑपरेशन का इस्तेमाल किया जा सकता है. इस कार्रवाई के लिए दो आर्ग्युमेंट दिए जाते हैं: एक अपडेट फ़ंक्शन और एक वैकल्पिक कॉलबैक. अपडेट फ़ंक्शन, डेटा की मौजूदा स्थिति को आर्ग्युमेंट के तौर पर लेता है और आपकी पसंद की नई स्थिति दिखाता है.
उदाहरण के लिए, सोशल ब्लॉगिंग ऐप्लिकेशन में, उपयोगकर्ताओं को पोस्ट को स्टार देने और स्टार हटाने की अनुमति दी जा सकती है. साथ ही, यह ट्रैक किया जा सकता है कि किसी पोस्ट को कितने स्टार मिले हैं. इसके लिए, यह तरीका अपनाएं:
Swift
ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in if var post = currentData.value as? [String: AnyObject], let uid = Auth.auth().currentUser?.uid { var stars: [String: Bool] stars = post["stars"] as? [String: Bool] ?? [:] var starCount = post["starCount"] as? Int ?? 0 if let _ = stars[uid] { // Unstar the post and remove self from stars starCount -= 1 stars.removeValue(forKey: uid) } else { // Star the post and add self to stars starCount += 1 stars[uid] = true } post["starCount"] = starCount as AnyObject? post["stars"] = stars as AnyObject? // Set value and report transaction success currentData.value = post return TransactionResult.success(withValue: currentData) } return TransactionResult.success(withValue: currentData) }) { error, committed, snapshot in if let error = error { print(error.localizedDescription) } }
Objective-C
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) { NSMutableDictionary *post = currentData.value; if (!post || [post isEqual:[NSNull null]]) { return [FIRTransactionResult successWithValue:currentData]; } NSMutableDictionary *stars = post[@"stars"]; if (!stars) { stars = [[NSMutableDictionary alloc] initWithCapacity:1]; } NSString *uid = [FIRAuth auth].currentUser.uid; int starCount = [post[@"starCount"] intValue]; if (stars[uid]) { // Unstar the post and remove self from stars starCount--; [stars removeObjectForKey:uid]; } else { // Star the post and add self to stars starCount++; stars[uid] = @YES; } post[@"stars"] = stars; post[@"starCount"] = @(starCount); // Set value and report transaction success currentData.value = post; return [FIRTransactionResult successWithValue:currentData]; } andCompletionBlock:^(NSError * _Nullable error, BOOL committed, FIRDataSnapshot * _Nullable snapshot) { // Transaction completed if (error) { NSLog(@"%@", error.localizedDescription); } }];
लेन-देन का इस्तेमाल करने से, स्टार की संख्या गलत होने से बचा जा सकता है. ऐसा तब होता है, जब कई उपयोगकर्ता एक ही समय पर एक ही पोस्ट को स्टार देते हैं या क्लाइंट के पास पुराना डेटा होता है. FIRMutableData क्लास में मौजूद वैल्यू, शुरुआत में पाथ के लिए क्लाइंट की आखिरी वैल्यू होती है. अगर कोई वैल्यू नहीं है, तो nil होती है. सर्वर, शुरुआती वैल्यू की तुलना मौजूदा वैल्यू से करता है. अगर वैल्यू मैच होती हैं, तो लेन-देन को स्वीकार करता है. अगर वैल्यू मैच नहीं होती हैं, तो लेन-देन को अस्वीकार कर देता है. अगर लेन-देन अस्वीकार कर दिया जाता है, तो सर्वर क्लाइंट को मौजूदा वैल्यू दिखाता है. इसके बाद, क्लाइंट अपडेट की गई वैल्यू के साथ लेन-देन को फिर से चलाता है. यह प्रोसेस तब तक दोहराई जाती है, जब तक लेन-देन स्वीकार नहीं हो जाता या कई बार कोशिश नहीं कर ली जाती.
सर्वर-साइड पर होने वाली बढ़ोतरी
ऊपर दिए गए इस्तेमाल के उदाहरण में, हम डेटाबेस में दो वैल्यू लिख रहे हैं: पोस्ट को स्टार/अनस्टार करने वाले उपयोगकर्ता का आईडी और स्टार की संख्या में बढ़ोतरी. अगर हमें पहले से पता है कि उपयोगकर्ता पोस्ट को स्टार कर रहा है, तो हम लेन-देन के बजाय, ऐटॉमिक इंक्रीमेंट ऑपरेशन का इस्तेमाल कर सकते हैं.
Swift
let updates = [ "posts/\(postID)/stars/\(userID)": true, "posts/\(postID)/starCount": ServerValue.increment(1), "user-posts/\(postID)/stars/\(userID)": true, "user-posts/\(postID)/starCount": ServerValue.increment(1) ] as [String : Any] Database.database().reference().updateChildValues(updates)
Objective-C
NSDictionary *updates = @{[NSString stringWithFormat: @"posts/%@/stars/%@", postID, userID]: @TRUE, [NSString stringWithFormat: @"posts/%@/starCount", postID]: [FIRServerValue increment:@1], [NSString stringWithFormat: @"user-posts/%@/stars/%@", postID, userID]: @TRUE, [NSString stringWithFormat: @"user-posts/%@/starCount", postID]: [FIRServerValue increment:@1]}; [[[FIRDatabase database] reference] updateChildValues:updates];
यह कोड, लेन-देन की कार्रवाई का इस्तेमाल नहीं करता. इसलिए, अगर कोई अपडेट मेल नहीं खाता है, तो यह अपने-आप फिर से नहीं चलता. हालांकि, इंक्रीमेंट ऑपरेशन सीधे डेटाबेस सर्वर पर होता है. इसलिए, किसी तरह की गड़बड़ी होने की संभावना नहीं होती.
अगर आपको ऐप्लिकेशन से जुड़ी समस्याओं का पता लगाना है और उन्हें अस्वीकार करना है, जैसे कि कोई उपयोगकर्ता किसी ऐसी पोस्ट को स्टार कर रहा है जिसे उसने पहले ही स्टार किया हुआ है, तो आपको उस इस्तेमाल के उदाहरण के लिए, सुरक्षा के कस्टम नियम लिखने चाहिए.
ऑफ़लाइन डेटा के साथ काम करना
अगर किसी क्लाइंट का इंटरनेट कनेक्शन टूट जाता है, तो भी आपका ऐप्लिकेशन ठीक से काम करता रहेगा.
Firebase डेटाबेस से कनेक्ट किया गया हर क्लाइंट, किसी भी ऐक्टिव डेटा का अपना इंटरनल वर्शन बनाए रखता है. जब डेटा सेव किया जाता है, तो वह सबसे पहले इस लोकल वर्शन में सेव होता है. इसके बाद, Firebase क्लाइंट उस डेटा को रिमोट डेटाबेस सर्वर और अन्य क्लाइंट के साथ "सबसे बेहतर तरीके" से सिंक करता है.
इस वजह से, डेटाबेस में कुछ भी लिखने पर, सर्वर में कोई डेटा लिखे जाने से पहले ही लोकल इवेंट तुरंत ट्रिगर हो जाते हैं. इसका मतलब है कि नेटवर्क की इंतज़ार की अवधि या कनेक्टिविटी की परवाह किए बिना, आपका ऐप्लिकेशन रिस्पॉन्सिव बना रहता है.
कनेक्टिविटी फिर से चालू होने पर, आपके ऐप्लिकेशन को इवेंट का सही सेट मिलता है. इससे क्लाइंट, सर्वर की मौजूदा स्थिति के साथ सिंक हो जाता है. इसके लिए, कोई कस्टम कोड लिखने की ज़रूरत नहीं पड़ती.
हम ऑनलाइन और ऑफ़लाइन सुविधाओं के बारे में ज़्यादा जानें लेख में, ऑफ़लाइन मोड के बारे में ज़्यादा बात करेंगे.