Home > Software engineering >  Firebase Realtime Database, how do I know when dataset has finished loading
Firebase Realtime Database, how do I know when dataset has finished loading

Time:12-05

How do I know when the dataset is loaded?

I have been using Firebase for over five years and love it. But, I have one question which I hope you can help with, but has been driving me mad for years.

I have many datasets stored on Firebase. What I need is a way to know when the dataset has been loaded. So, if there are 1000 records at the node /Main/PNG/flight/airstrip I want to know when I have received all leaves.

I have tried using .value and subscribe to the whole node using

Database.database().reference(withPath: key).observe(.value) { [weak self, key] snapshot ...}

And then I will know when the dataset comes in because I will get just one snapshot containing a dictionary of all the leaves, but I don't get the deltas (changes and additions).

and I have subscribed to all the leaves, using

[.childChanged, .childRemoved, .childAdded].forEach { eventType in
Database.database().reference(withPath: key).observe(eventType) { [weak self, storeEventType] snapshot in ...}

But, then I don’t know when I have received all of the dataset.

My datamodel is based on an Initial Snapshot followed by listening to any changes to the leaves. The initial snapshot is easy using

Database.database().reference(withPath: key).observe(.value) { [weak self, key] snapshot ...}

but when I follow this with

[.childChanged, .childRemoved, .childAdded].forEach { eventType in
Database.database().reference(withPath: key).observe(eventType) { [weak self, storeEventType] snapshot in ...}

I get the complete dataset again.

What I would like is either:

  1. to .observe(.childAdded) and somehow know when all the leaves have completed, at least for this dataset,
  2. or to use .observe(.childAdded) without receiving an initial dataset of all the leaves, but then I need to work out if I missed anything between the .observe(.value) and .observe(.childAdded) calls.

I know that I could view the dataset as an endless number of deltas and changes, so therefore there isn’t an END OF SET, but updating a UITableView in Swift is easier if I know lots of records are queued, in which case I can call a reloadData() on the UITableview. But, if there are just a few records queued, I prefer to let the tableView animate nicely, a row at a time.

CodePudding user response:

When an entire snapshot is loaded, the Firebase SDK fires the value event. So even if you use the child* events for actually handling the data, you can implement a value listener to detect when the loading is done.

Implementing both child* and value event listeners does not double the amount of data that gets load. The Firebase SDK deduplicates the listeners behind the scenes.

CodePudding user response:

If you want to know when the initial dataset has been loaded, you can use the FIRDataEventTypeValue event type to listen for changes to the value of the reference you are querying. This event will be triggered once when the initial data is loaded, and then again whenever the data at that reference changes.

To avoid receiving the initial dataset again when you start listening for child events, you can use the FIRDataEventTypeChildAdded event type to listen for changes to the children of the reference you are querying. This event will only be triggered when a new child is added to the reference, and will not be triggered when the initial data is loaded.

Here is an example of how you could use these event types to know when the initial dataset has been loaded and when new children are added:

// Listen for changes to the value of the reference
Database.database().reference(withPath: key).observe(.value) { snapshot in
  // This block will be called once when the initial data is loaded,
  // and then again whenever the data at the reference changes
}

// Listen for changes to the children of the reference
Database.database().reference(withPath: key).observe(.childAdded) { snapshot in
  // This block will be called whenever a new child is added to the reference
}

Alternatively, if you want to know when all the leaves have been loaded, you can use the FIRDataEventTypeValue event type to listen for changes to the value of the reference you are querying, and then use the children property of the snapshot to access the list of children that have been loaded. When the children property contains all the children you are expecting, you can use this information to know that all the leaves have been loaded.

Here is an example of how you could use this approach to know when all the leaves have been loaded:

// Listen for changes to the value of the reference

Database.database().reference(withPath: key).observe(.value) { snapshot in
  // Get the list of children that have been loaded
  let children = snapshot.children
  
  // Check if the list of children contains all the leaves you are expecting
  if children.count == expectedLeafCount {
    // All the leaves have been loaded
  }
}

I hope this helps!

  • Related