简体   繁体   中英

Firebase real-time efficiency question: How to set up listeners for a chat app

I have a chat app using Firebase as a realtime database and React Native. I'm trying to figure out the most efficient way to set up the listener for chat messages from Firebase in terms of minimizing read operations and transferring data. Here is my data structure:

- messages
  - chatId
    - messageId
      - sentBy
      - timestamp
      - text

As I see it I have 2 options, either ref.on("child_added) or ref.on("value")

If I use ref.on("child_added") , the advantage is that when a new message is sent then only the newest message is retrieved. The problem though is that when the conversation is loaded the read operation is called for each message in the chat. If a conversation is hundreds of messages long, then that's hundreds of read operations.

The other option is to use ref.on("value") . The problem here is that on every new message added, the entire conversation is resent instead of just the most recent message. The advantage is that when the conversation is loaded, only one read operation is called to transfer the entire conversation to the screen.

I want some combination of the two of these in which when the conversation is loaded, there is one read operation that brings the entire contents of the conversation, AND when a new child node is added (a new message) only that message is transmitted to the listener. How can I achieve this?

Suggestion: Use Firestore. It maintains a cache of your data and efficiently handles such scenarios.


You can use ref.once('value') to get current nodes only once and then ref.on('child_added') for subsequent additions. More performance notes.

Edit: I believe Firebase Database handles this efficiently by just ref.on('value') . On checking the network tab after adding a new node to my database, I notified the amount of data that got transferred was very low. This might mean that firebase by default caches your previous data. Would recommend you to look at your network tab and take decisions as such or wait from someone from their team show directions.

firebaser here

There is no difference between the wire traffic for a value listener and child_ listeners on the same location/query. If you check the Network tab of your browser, you can see exactly what is sent retrieved, and you'll see that it's exactly the same between the listener types.

The difference between value and child_* events is purely made client-side to make it easier for you to update the UI. In fact, even when you attach both value and child_* listeners to the same query/location, Firebase will only retrieve the data only once.

The common way to do what you want is to attach both child_* and value listeners to the query/location. Since the value listener is guaranteed to be fired last, you can use that fact to detect when the initial load is done.

Something like:

var chatRef = firebase.database().ref("messages/chatId");
var initialLoadDone = false;
chatRef.on("child_added", (snapshot) => {
  if (initialLoadDone) {
    ...
  }
});
chatRef.once("value", (snapshot) => {
  snapshot.forEach((messageSnapshot) => {
    ...
  });
  initialLoadDone = true;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM