15

I'm making a simple app that informs a client that other clients clicked a button. I'm storing the clicks in a Firebase (db) using:

db.push({msg:data}); 

All clients get notified of other user's clicks with an on, such as

db.on('child_added',function(snapshot) { var msg = snapshot.val().msg; }); 

However, when the page first loads I want to discard any existing data on the stack. My strategy is to call db.once() before I define the db.on('child_added',...) in order to get the initial number of children, and then use that to discard that number of calls to db.on('child_added',...).

Unfortunately, though, all of the calls to db.on('child_added',...) are happening before I'm able to get the initial count, so it fails.

How can I effectively and simply discard the initial data?

2
  • See also: How to retrieve only new data Commented Jan 16, 2015 at 16:06
  • 1
    Since the common use case for this question is creating a message queue, the best answer is to use a message queue strategy, where events are added and deleted from a queue, and not bother with this added complexity. Please consider that route before any of the answers below. Commented Jan 31, 2015 at 17:40

2 Answers 2

27

For larger data sets, Firebase now offers (as of 2.0) some query methods that can make this simpler.

If we add a timestamp field on each record, we can construct a query that only looks at new values. Consider this contrived data:

{ "messages": { "$messageid": { "sender": "kato", "message": "hello world" "created": 123456 // Firebase.ServerValue.TIMESTAMP } } } 

We could find messages only after "now" using something like this:

var ref = new Firebase('https://<your instance>.firebaseio.com/messages'); var queryRef = ref.orderBy('created').startAt(Firebase.ServerValue.TIMESTAMP); queryRef.on('child_added', function(snap) { console.log(snap.val()); }); 
Sign up to request clarification or add additional context in comments.

8 Comments

How would you deal with inconsistency if I create a new record myself with REST API and set created timestamp as my server's timestamp? Which is ofcourse UTC too, but you know it may not match exactly Firebase's time
Use Firebase.ServerValue.TIMESTAMP and there won't be any inconsistencies. If you're worried about someone hacking your software to set inconsistent times--they must really be bored--then use security rules to enforce the timestamps consistency.
Thanks alot, I looked now again, REST API does indeed support setting Firebase timestamp '{".sv": "timestamp"}' firebase.com/docs/rest/api/#section-server-values
hello kato, your above example doesnt work, orderBy does not exist in firebase's javascript lib, only in REST API. Also it seems that firebase timestamp (which is just json object) cannot be passed to startAt, in the example docs, startAt was taking only integers. Please refer to my updated question stackoverflow.com/questions/30493719/…
This question was asked over a year ago. The API has changed since then. See queries and any of the orderBy*() methods.
|
17

If I understand your question correctly, it sounds like you only want data that has been added since the user visited the page. In Firebase, the behavior you describe is by design, as the data is always changing and there isn't a notion of "old" data vs "new" data.

However, if you only want to display data added after the page has loaded, try ignoring all events prior until the complete set of children has loaded at least once. For example:

var ignoreItems = true; var ref = new Firebase('https://<your-Firebase>.firebaseio.com'); ref.on('child_added', function(snapshot) { if (!ignoreItems) { var msg = snapshot.val().msg; // do something here } }); ref.once('value', function(snapshot) { ignoreItems = false; }); 

The alternative to this approach would be to write your new items with a priority as well, where the priority is Firebase.ServerValue.TIMESTAMP (the current server time), and then use a .startAt(...) query using the current timestamp. However, this is more complex than the approach described above.

4 Comments

yes, that's what I'm looking for. I was trying a variation on that but mine was more complicated. thx!
This solution requires the data be downloaded twice which is non-ideal for large data sets. Also, if the data set is large enough, value will take a long time to load and some items in child_added could be missed.
It is true that some items could be missed if the data set is sufficiently large, but it does not cause the data to be downloaded twice. In general, if only querying for "new items since a particular client came online", it is a better bet to query data based upon timestamp, or use a pub-sub model.
Yes, I do the same thing. I do a chat application, and have a ChatManager singleton to be the first handler of firebase events then notify other listeners by using Observer design pattern. When the ChatManager init, I wait for 4-5s before turn on should_handle_event variable. Any event comes before that will be discard.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.