شما میتوانید با استفاده از متد onSnapshot() به یک سند گوش دهید . یک فراخوانی اولیه با استفاده از فراخوانی که شما ارائه میدهید، بلافاصله یک snapshot از سند با محتوای فعلی سند ایجاد میکند. سپس، هر بار که محتوا تغییر میکند، فراخوانی دیگری snapshot سند را بهروزرسانی میکند.
import { doc, onSnapshot } from "firebase/firestore"; const unsub = onSnapshot(doc(db, "cities", "SF"), (doc) => { console.log("Current data: ", doc.data()); });
db.collection("cities").doc("SF") .onSnapshot((doc) => { console.log("Current data: ", doc.data()); });
db.collection("cities").document("SF") .addSnapshotListener { documentSnapshot, error in guard let document = documentSnapshot else { print("Error fetching document: \(error!)") return } guard let data = document.data() else { print("Document data was empty.") return } print("Current data: \(data)") }
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching document: %@", error); return; } NSLog(@"Current data: %@", snapshot.data); }];
val docRef = db.collection("cities").document("SF") docRef.addSnapshotListener { snapshot, e -> if (e != null) { Log.w(TAG, "Listen failed.", e) return@addSnapshotListener } if (snapshot != null && snapshot.exists()) { Log.d(TAG, "Current data: ${snapshot.data}") } else { Log.d(TAG, "Current data: null") } }
final DocumentReference docRef = db.collection("cities").document("SF"); docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen failed.", e); return; } if (snapshot != null && snapshot.exists()) { Log.d(TAG, "Current data: " + snapshot.getData()); } else { Log.d(TAG, "Current data: null"); } } });
final docRef = db.collection("cities").doc("SF"); docRef.snapshots().listen( (event) => print("current data: ${event.data()}"), onError: (error) => print("Listen failed: $error"), );
اغلب، شما میخواهید رابط کاربری شما به تغییرات در محتوای یک سند یا مجموعه Firestore واکنش نشان دهد. میتوانید این کار را با یک ویجت StreamBuilder که جریان snapshot Firestore را مصرف میکند، انجام دهید:
class UserInformation extends StatefulWidget { @override _UserInformationState createState() => _UserInformationState(); } class _UserInformationState extends State<UserInformation> { final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance.collection('users').snapshots(); @override Widget build(BuildContext context) { return StreamBuilder<QuerySnapshot>( stream: _usersStream, builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) { if (snapshot.hasError) { return const Text('Something went wrong'); } if (snapshot.connectionState == ConnectionState.waiting) { return const Text("Loading"); } return ListView( children: snapshot.data!.docs .map((DocumentSnapshot document) { Map<String, dynamic> data = document.data()! as Map<String, dynamic>; return ListTile( title: Text(data['full_name']), subtitle: Text(data['company']), ); }) .toList() .cast(), ); }, ); } }
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.AddSnapshotListener( [](const DocumentSnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { if (snapshot.exists()) { std::cout << "Current data: " << snapshot << std::endl; } else { std::cout << "Current data: null" << std::endl; } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not supported in the PHP client libraryDocumentReference docRef = db.Collection("cities").Document("SF"); docRef.Listen(snapshot => { Debug.Log("Callback received document snapshot."); Debug.Log(String.Format("Document data for {0} document:", snapshot.Id)); Dictionary<string, object> city = snapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Debug.Log(String.Format("{0}: {1}", pair.Key, pair.Value)); } });
نوشتنهای محلی در برنامه شما بلافاصله شنوندههای snapshot را فراخوانی میکنند. این به دلیل ویژگی مهمی به نام "جبران تأخیر" است. وقتی نوشتنی انجام میدهید، شنوندههای شما قبل از ارسال دادهها به backend، از دادههای جدید مطلع میشوند.
اسناد بازیابی شده دارای خاصیتی metadata.hasPendingWrites هستند که نشان میدهد آیا سند دارای تغییرات محلی است که هنوز در backend نوشته نشدهاند یا خیر. میتوانید از این خاصیت برای تعیین منبع رویدادهای دریافت شده توسط snapshot listener خود استفاده کنید:
import { doc, onSnapshot } from "firebase/firestore"; const unsub = onSnapshot(doc(db, "cities", "SF"), (doc) => { const source = doc.metadata.hasPendingWrites ? "Local" : "Server"; console.log(source, " data: ", doc.data()); });
db.collection("cities").doc("SF") .onSnapshot((doc) => { var source = doc.metadata.hasPendingWrites ? "Local" : "Server"; console.log(source, " data: ", doc.data()); });
db.collection("cities").document("SF") .addSnapshotListener { documentSnapshot, error in guard let document = documentSnapshot else { print("Error fetching document: \(error!)") return } let source = document.metadata.hasPendingWrites ? "Local" : "Server" print("\(source) data: \(document.data() ?? [:])") }
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching document: %@", error); return; } NSString *source = snapshot.metadata.hasPendingWrites ? @"Local" : @"Server"; NSLog(@"%@ data: %@", source, snapshot.data); }];
val docRef = db.collection("cities").document("SF") docRef.addSnapshotListener { snapshot, e -> if (e != null) { Log.w(TAG, "Listen failed.", e) return@addSnapshotListener } val source = if (snapshot != null && snapshot.metadata.hasPendingWrites()) { "Local" } else { "Server" } if (snapshot != null && snapshot.exists()) { Log.d(TAG, "$source data: ${snapshot.data}") } else { Log.d(TAG, "$source data: null") } }
final DocumentReference docRef = db.collection("cities").document("SF"); docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen failed.", e); return; } String source = snapshot != null && snapshot.getMetadata().hasPendingWrites() ? "Local" : "Server"; if (snapshot != null && snapshot.exists()) { Log.d(TAG, source + " data: " + snapshot.getData()); } else { Log.d(TAG, source + " data: null"); } } });
final docRef = db.collection("cities").doc("SF"); docRef.snapshots().listen( (event) { final source = (event.metadata.hasPendingWrites) ? "Local" : "Server"; print("$source data: ${event.data()}"); }, onError: (error) => print("Listen failed: $error"), );
# Not yet supported in the Java client library
// Not yet supported in Python client library
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.AddSnapshotListener([](const DocumentSnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { const char* source = snapshot.metadata().has_pending_writes() ? "Local" : "Server"; if (snapshot.exists()) { std::cout << source << " data: " << snapshot.Get("name").string_value() << std::endl; } else { std::cout << source << " data: null" << std::endl; } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not yet supported in the Node.js client library// Not yet supported in the Go client library// Not supported in the PHP client libraryDocumentReference docRef = db.Collection("cities").Document("SF"); docRef.Listen( snapshot => { string source = (snapshot != null && snapshot.Metadata.HasPendingWrites) ? "Local" : "Server"; string snapshotData = "null"; if (snapshot != null && snapshot.Exists) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); IDictionary<string, object> dict = snapshot.ToDictionary(); foreach (var KVPair in dict) { builder.Append($"{KVPair.Key}: {KVPair.Value}\n"); } snapshotData = builder.ToString(); } Debug.Log($"{source} data: ${snapshotData}"); });
// Not yet supported in the C# client library// Not yet supported in the Ruby client library
هنگام گوش دادن به تغییرات در یک سند، مجموعه یا پرس و جو، میتوانید گزینههایی را برای کنترل جزئیات رویدادهایی که شنونده شما دریافت خواهد کرد، ارسال کنید.
به طور پیشفرض، شنوندهها از تغییراتی که فقط بر ابرداده تأثیر میگذارند، مطلع نمیشوند. در نظر بگیرید وقتی برنامه شما یک سند جدید مینویسد چه اتفاقی میافتد:
- یک رویداد تغییر بلافاصله با دادههای جدید اجرا میشود. سند هنوز در backend نوشته نشده است، بنابراین پرچم "pending write"
trueاست. - سند در backend نوشته شده است.
- بخش مدیریت، کلاینت را از نوشتن موفقیتآمیز مطلع میکند. هیچ تغییری در دادههای سند ایجاد نشده است، اما به دلیل اینکه پرچم «در انتظار نوشتن» اکنون
falseاست، تغییری در فراداده رخ داده است.
اگر میخواهید هنگام تغییر ابرداده سند یا پرسوجو، رویدادهای snapshot را دریافت کنید، هنگام اتصال شنونده خود، یک شیء listen options ارسال کنید.
import { doc, onSnapshot } from "firebase/firestore"; const unsub = onSnapshot( doc(db, "cities", "SF"), { includeMetadataChanges: true }, (doc) => { // ... });
db.collection("cities").doc("SF") .onSnapshot({ // Listen for document metadata changes includeMetadataChanges: true }, (doc) => { // ... });
// Listen to document metadata. db.collection("cities").document("SF") .addSnapshotListener(includeMetadataChanges: true) { documentSnapshot, error in // ... }
// Listen for metadata changes. [[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListenerWithIncludeMetadataChanges:YES listener:^(FIRDocumentSnapshot *snapshot, NSError *error) { // ... }];
// Listen for metadata changes to the document. val docRef = db.collection("cities").document("SF") docRef.addSnapshotListener(MetadataChanges.INCLUDE) { snapshot, e -> // ... }
// Listen for metadata changes to the document. DocumentReference docRef = db.collection("cities").document("SF"); docRef.addSnapshotListener(MetadataChanges.INCLUDE, new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) { // ... } });
final docRef = db.collection("cities").doc("SF"); docRef.snapshots(includeMetadataChanges: true).listen((event) { // ... });
// Not yet supported in the Java client library// Not yet supported in Python client library
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.AddSnapshotListener( MetadataChanges::kInclude, [](const DocumentSnapshot& snapshot, Error error, const std::string& errorMsg) { /* ... */ });
// Not yet supported the Node.js client library// Not yet supported in the Go client library// Not supported in the PHP client libraryDocumentReference docRef = db.Collection("cities").Document("SF"); docRef.Listen(MetadataChanges.Include, snapshot => { // ... });
// Not yet supported in the C# client library// Not yet supported in the Ruby client library
شنوندگان اسنپشات Cloud Firestore یک اسنپشات اولیه از حافظه پنهان محلی میگیرند و همزمان دادههای مربوطه را از سرور دریافت میکنند.
در برخی موارد، ممکن است نخواهید واکشیهای بعدی از سرور انجام شود. SDKهای کلاینت به شما این امکان را میدهند که شنوندهها را طوری پیکربندی کنید که فقط با توجه به دادههای موجود در حافظه پنهان محلی اجرا شوند. این به شما کمک میکند از فراخوانیهای غیرضروری سرور و هزینههای آنها جلوگیری کنید و از حافظه پنهان سمت کلاینت که دادههای محلی و جهشها را منعکس میکند، بهره ببرید.
در اینجا، گزینههای snapshot در کد کلاینت تنظیم شدهاند تا فقط امکان گوش دادن به تغییرات محلی را فراهم کنند.
const unsubscribe = onSnapshot( doc(db, "cities", "SF"), { includeMetadataChanges: true, source:'cache' }, (documentSnapshot) => {//…} );
// Not yet supported in the Web namespaced API// Set up listener options
let options = SnapshotListenOptions()
.withSource(ListenSource.cache)
.withIncludeMetadataChanges(true)
db.collection("cities").document("SF")
.addSnapshotListener(options: options) { documentSnapshot, error in
// ...
}
// Set up listener options
FIRSnapshotListenOptions *options = [[FIRSnapshotListenOptions alloc] init];
FIRSnapshotListenOptions *optionsWithSourceAndMetadata =
[[options optionsWithIncludeMetadataChanges:YES]
optionsWithSource:FIRListenSourceCache];
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"]
addSnapshotListenerWithOptions:optionsWithSourceAndMetadata
listener: ^ (FIRDocumentSnapshot * snapshot, NSError * error) {
//…
}
];
// Set up listener options
val options = SnapshotListenOptions.Builder()
.setMetadataChanges(MetadataChanges.INCLUDE)
.setSource(ListenSource.CACHE)
.build();
db.collection("cities").document("SF")
.addSnapshotListener(options) { snapshot, error ->
//…
}
// Set up listener options
SnapshotListenOptions options = new SnapshotListenOptions.Builder()
.setMetadataChanges(MetadataChanges.INCLUDE)
.setSource(ListenSource.CACHE)
.build();
db.collection("cities").document("SF").addSnapshotListener(options, new EventListener<DocumentSnapshot>() {
//…
});
// Not yet supported in this client library
# Not yet supported in the Java client library
// Not yet supported in Python client library
// Not yet supported in the C++ client library// Not yet supported in the Node.js client library// Not yet supported in the Go client library// Not yet supported in the PHP client library// Not yet supported in the Unity client library// Not yet supported in the C# client library// Not yet supported in the Ruby client library
همانند اسناد، میتوانید به جای get() از onSnapshot() ) برای گوش دادن به نتایج یک پرسوجو استفاده کنید. این یک تصویر لحظهای از پرسوجو ایجاد میکند. به عنوان مثال، برای گوش دادن به اسناد با وضعیت CA :
import { collection, query, where, onSnapshot } from "firebase/firestore"; const q = query(collection(db, "cities"), where("state", "==", "CA")); const unsubscribe = onSnapshot(q, (querySnapshot) => { const cities = []; querySnapshot.forEach((doc) => { cities.push(doc.data().name); }); console.log("Current cities in CA: ", cities.join(", ")); });
db.collection("cities").where("state", "==", "CA") .onSnapshot((querySnapshot) => { var cities = []; querySnapshot.forEach((doc) => { cities.push(doc.data().name); }); console.log("Current cities in CA: ", cities.join(", ")); });
db.collection("cities").whereField("state", isEqualTo: "CA") .addSnapshotListener { querySnapshot, error in guard let documents = querySnapshot?.documents else { print("Error fetching documents: \(error!)") return } let cities = documents.compactMap { $0["name"] } print("Current cities in CA: \(cities)") }
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching documents: %@", error); return; } NSMutableArray *cities = [NSMutableArray array]; for (FIRDocumentSnapshot *document in snapshot.documents) { [cities addObject:document.data[@"name"]]; } NSLog(@"Current cities in CA: %@", cities); }];
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener { value, e -> if (e != null) { Log.w(TAG, "Listen failed.", e) return@addSnapshotListener } val cities = ArrayList<String>() for (doc in value!!) { doc.getString("name")?.let { cities.add(it) } } Log.d(TAG, "Current cites in CA: $cities") }
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen failed.", e); return; } List<String> cities = new ArrayList<>(); for (QueryDocumentSnapshot doc : value) { if (doc.get("name") != null) { cities.add(doc.getString("name")); } } Log.d(TAG, "Current cites in CA: " + cities); } });
db .collection("cities") .where("state", isEqualTo: "CA") .snapshots() .listen((event) { final cities = []; for (var doc in event.docs) { cities.add(doc.data()["name"]); } print("cities in CA: ${cities.join(", ")}"); });
db->Collection("cities") .WhereEqualTo("state", FieldValue::String("CA")) .AddSnapshotListener([](const QuerySnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { std::vector<std::string> cities; std::cout << "Current cities in CA: " << error << std::endl; for (const DocumentSnapshot& doc : snapshot.documents()) { cities.push_back(doc.Get("name").string_value()); std::cout << "" << cities.back() << std::endl; } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not supported in the PHP client libraryQuery query = db.Collection("cities").WhereEqualTo("State", "CA"); ListenerRegistration listener = query.Listen(snapshot => { Debug.Log("Callback received query snapshot."); Debug.Log("Current cities in California:"); foreach (DocumentSnapshot documentSnapshot in snapshot.Documents) { Debug.Log(documentSnapshot.Id); } });
هر بار که نتایج پرسوجو تغییر کند (یعنی وقتی یک سند اضافه، حذف یا اصلاح میشود)، کنترلکنندهی اسنپشات، یک اسنپشات پرسوجوی جدید دریافت میکند.
اغلب مفید است که تغییرات واقعی نتایج پرسوجو را بین اسنپشاتهای پرسوجو مشاهده کنید، نه اینکه صرفاً از کل اسنپشات پرسوجو استفاده کنید. به عنوان مثال، ممکن است بخواهید همزمان با اضافه شدن، حذف شدن و تغییر اسناد، یک کش (cache) را حفظ کنید.
import { collection, query, where, onSnapshot } from "firebase/firestore"; const q = query(collection(db, "cities"), where("state", "==", "CA")); const unsubscribe = onSnapshot(q, (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } if (change.type === "modified") { console.log("Modified city: ", change.doc.data()); } if (change.type === "removed") { console.log("Removed city: ", change.doc.data()); } }); });
db.collection("cities").where("state", "==", "CA") .onSnapshot((snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } if (change.type === "modified") { console.log("Modified city: ", change.doc.data()); } if (change.type === "removed") { console.log("Removed city: ", change.doc.data()); } }); });
db.collection("cities").whereField("state", isEqualTo: "CA") .addSnapshotListener { querySnapshot, error in guard let snapshot = querySnapshot else { print("Error fetching snapshots: \(error!)") return } snapshot.documentChanges.forEach { diff in if (diff.type == .added) { print("New city: \(diff.document.data())") } if (diff.type == .modified) { print("Modified city: \(diff.document.data())") } if (diff.type == .removed) { print("Removed city: \(diff.document.data())") } } }
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching documents: %@", error); return; } for (FIRDocumentChange *diff in snapshot.documentChanges) { if (diff.type == FIRDocumentChangeTypeAdded) { NSLog(@"New city: %@", diff.document.data); } if (diff.type == FIRDocumentChangeTypeModified) { NSLog(@"Modified city: %@", diff.document.data); } if (diff.type == FIRDocumentChangeTypeRemoved) { NSLog(@"Removed city: %@", diff.document.data); } } }];
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener { snapshots, e -> if (e != null) { Log.w(TAG, "listen:error", e) return@addSnapshotListener } for (dc in snapshots!!.documentChanges) { when (dc.type) { DocumentChange.Type.ADDED -> Log.d(TAG, "New city: ${dc.document.data}") DocumentChange.Type.MODIFIED -> Log.d(TAG, "Modified city: ${dc.document.data}") DocumentChange.Type.REMOVED -> Log.d(TAG, "Removed city: ${dc.document.data}") } } }
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot snapshots, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "listen:error", e); return; } for (DocumentChange dc : snapshots.getDocumentChanges()) { switch (dc.getType()) { case ADDED: Log.d(TAG, "New city: " + dc.getDocument().getData()); break; case MODIFIED: Log.d(TAG, "Modified city: " + dc.getDocument().getData()); break; case REMOVED: Log.d(TAG, "Removed city: " + dc.getDocument().getData()); break; } } } });
db .collection("cities") .where("state", isEqualTo: "CA") .snapshots() .listen((event) { for (var change in event.docChanges) { switch (change.type) { case DocumentChangeType.added: print("New City: ${change.doc.data()}"); break; case DocumentChangeType.modified: print("Modified City: ${change.doc.data()}"); break; case DocumentChangeType.removed: print("Removed City: ${change.doc.data()}"); break; } } });
db->Collection("cities") .WhereEqualTo("state", FieldValue::String("CA")) .AddSnapshotListener([](const QuerySnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { for (const DocumentChange& dc : snapshot.DocumentChanges()) { switch (dc.type()) { case DocumentChange::Type::kAdded: std::cout << "New city: " << dc.document().Get("name").string_value() << std::endl; break; case DocumentChange::Type::kModified: std::cout << "Modified city: " << dc.document().Get("name").string_value() << std::endl; break; case DocumentChange::Type::kRemoved: std::cout << "Removed city: " << dc.document().Get("name").string_value() << std::endl; break; } } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not supported in the PHP client libraryQuery query = db.Collection("cities").WhereEqualTo("State", "CA"); ListenerRegistration listener = query.Listen(snapshot => { foreach (DocumentChange change in snapshot.GetChanges()) { if (change.ChangeType == DocumentChange.Type.Added) { Debug.Log(String.Format("New city: {0}", change.Document.Id)); } else if (change.ChangeType == DocumentChange.Type.Modified) { Debug.Log(String.Format("Modified city: {0}", change.Document.Id)); } else if (change.ChangeType == DocumentChange.Type.Removed) { Debug.Log(String.Format("Removed city: {0}", change.Document.Id)); } } });
وضعیت اولیه میتواند مستقیماً از سرور یا از یک حافظه پنهان محلی دریافت شود. اگر وضعیتی در حافظه پنهان محلی موجود باشد، تصویر لحظهای پرسوجو در ابتدا با دادههای ذخیرهشده پر میشود و سپس هنگامی که کلاینت به وضعیت سرور دسترسی پیدا کرد، با دادههای سرور بهروزرسانی میشود.
وقتی دیگر علاقهای به گوش دادن به دادههای خود ندارید، باید شنونده خود را جدا کنید تا فراخوانی رویدادهای برگشتی شما متوقف شود. این به کلاینت اجازه میدهد تا استفاده از پهنای باند برای دریافت بهروزرسانیها را متوقف کند. برای مثال:
import { collection, onSnapshot } from "firebase/firestore"; const unsubscribe = onSnapshot(collection(db, "cities"), () => { // Respond to data // ... }); // Later ... // Stop listening to changes unsubscribe();
var unsubscribe = db.collection("cities") .onSnapshot(() => { // Respond to data // ... }); // Later ... // Stop listening to changes unsubscribe();
let listener = db.collection("cities").addSnapshotListener { querySnapshot, error in // ... } // ... // Stop listening to changes listener.remove()
id<FIRListenerRegistration> listener = [[self.db collectionWithPath:@"cities"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { // ... }]; // ... // Stop listening to changes [listener remove];
val query = db.collection("cities") val registration = query.addSnapshotListener { snapshots, e -> // ... } // ... // Stop listening to changes registration.remove()
Query query = db.collection("cities"); ListenerRegistration registration = query.addSnapshotListener( new EventListener<QuerySnapshot>() { // ... }); // ... // Stop listening to changes registration.remove();
final collection = db.collection("cities"); final listener = collection.snapshots().listen((event) { // ... }); listener.cancel();
// Add a listener Query query = db->Collection("cities"); ListenerRegistration registration = query.AddSnapshotListener( [](const QuerySnapshot& snapshot, Error error, const std::string& errorMsg) { /* ... */ }); // Stop listening to changes registration.Remove();
// Not supported in the PHP client librarylistener.Stop();
ممکن است گاهی اوقات شنود با شکست مواجه شود - برای مثال، به دلیل مجوزهای امنیتی، یا اگر سعی کردهاید به یک پرسوجوی نامعتبر گوش دهید. (درباره پرسوجوهای معتبر و نامعتبر بیشتر بدانید.) برای مدیریت این شکستها، میتوانید هنگام اتصال شنودگر snapshot خود، یک callback خطا ارائه دهید. پس از یک خطا، شنودگر دیگر هیچ رویدادی را دریافت نمیکند و نیازی به جدا کردن شنودگر شما نیست.
import { collection, onSnapshot } from "firebase/firestore"; const unsubscribe = onSnapshot( collection(db, "cities"), (snapshot) => { // ... }, (error) => { // ... });
db.collection("cities") .onSnapshot((snapshot) => { // ... }, (error) => { // ... });
db.collection("cities") .addSnapshotListener { querySnapshot, error in if let error = error { print("Error retreiving collection: \(error)") } }
[[self.db collectionWithPath:@"cities"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error retreving collection: %@", error); } }];
db.collection("cities") .addSnapshotListener { snapshots, e -> if (e != null) { Log.w(TAG, "listen:error", e) return@addSnapshotListener } for (dc in snapshots!!.documentChanges) { if (dc.type == DocumentChange.Type.ADDED) { Log.d(TAG, "New city: ${dc.document.data}") } } }
db.collection("cities") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot snapshots, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "listen:error", e); return; } for (DocumentChange dc : snapshots.getDocumentChanges()) { if (dc.getType() == Type.ADDED) { Log.d(TAG, "New city: " + dc.getDocument().getData()); } } } });
final docRef = db.collection("cities"); docRef.snapshots().listen( (event) => print("listener attached"), onError: (error) => print("Listen failed: $error"), );
// Snippet coming soon
// Snippet coming soon.// Not supported in the PHP client libraryListenerRegistration registration = db.Collection("cities").Listen( querySnapshot => { // ... }); registration.ListenerTask.ContinueWithOnMainThread( listenerTask => { if (listenerTask.IsFaulted) { Debug.LogError($"Listen failed: {listenerTask.Exception}"); // ... // Handle the listener error. // ... } });
// Snippet coming soonقیمتگذاری برای عملیات شنود بلادرنگ به نسخه پایگاه داده بستگی دارد. به موارد زیر مراجعه کنید:
- شنوندهها را با کوئریهای ساده و مرکب ترکیب کنید .
- اسناد بازیابی شده را مرتب و محدود کنید .
- صورتحساب برای شنوندگان را درک کنید .