问题
I've created this handler to watch for new children being created. This little trick stops the child_added event from triggering my code on each page load. Instead it only gets triggered when something is actually added.
// Listen for new rooms being created
var first_room_added_after_load = true;
this._roomRef.endAt().limit(1).on('child_added', function(snapshot){
if (first_room_added_after_load) { // we want to skip the first room, because it will already exist
first_room_added_after_load = false;
return;
}
else {
this._onCreateRoom(snapshot);
}
}, this);
That said, when I call remove() on a node in _roomRef then child_added is triggered for a node that already exists. Any hints as to why, and how to stop it?
I should also mention this only seems to happen if I remove something that was created after something else already in the list. If I remove the older items first, then child_added is not triggered.
回答1:
You seem to think the endAt()
uses a timestamp for comparison, so that it only returns new children. But that's simply not how it works. From the Firebase documentation for endAt:
If no arguments are provided, the ending point will be the end of the data.
With your code:
this._roomRef.endAt().limit(1)
You're creating a query that is set to always return a single child. The condition is that the child was created after you created the query.
A query is like a sliding window over the child nodes in your Firebase ref: it will always contain (at most) one child, a child that was created after you created your query.
Example
Say you have these children when you create the query:
child1
child2
child3 <!-- last child present when creating the endAt() query -->
By using endAt
query will be "rooted" after child3
. So it will not fire any events for child1
, child2
and child3
.
Say you add a new child:
child1
child2
child3 <!-- last child present when creating the endAt() query -->
child4
The query will a child_added
event for child4
.
Now if we add another child:
child1
child2
child3 <!-- last child present when creating the endAt() query -->
child4
child5
The query will fire a child_removed
for child4
and child_added
for child5
. Note that child4
was not actually removed from your Firebase, it just disappeared from the query results (since you asked to limit the number of results to just one).
When we now remove the latest child, we end up with:
child1
child2
child3 <!-- last child present when creating the endAt() query -->
child4
And the query will fire a child_removed
for child5
and child_added
for child4
. This again comes from the fact that your query is set to always contain (at most) one node that was added after child3
.
How to get what you want
It seems like you only want to get child_added
once for newly added children. In that case I would not use a limit
on the query, but instead I would set the timestamp that the room was created as its priority:
this._roomRef.push({
/* whatever properties you need for a room */,
'.priority': Firebase.ServerValue.TIMESTAMP
})
Then you can simply start the query at that priority.
this._roomRef.startAt(Date.now()).on('child_added', ...
回答2:
I found a tricky solution for this . Let's suppose you are getting messages with value like msg-txt , timestamp , userid When you get the first messages using child_added you need to store the latest message timestamp into a global variable then for every new chils_added just compare the two timestamps .
If the message timestamp > the global timestamp Then return the message and save its timestamp to global timestamp.
Hope this will help
来源:https://stackoverflow.com/questions/25235283/child-added-gets-triggered-after-remove