问题
I have a live listener on my database data in my HTML table that is generated by javascript and when I add a new entry or delete an old entry, the data that was previously in the table gets duplicated.
var database = firebase.database().ref().child('transactions');
database.on('value', function(snapshot){
if(snapshot.exists()){
var content = '';
snapshot.forEach(function(data){
var CustomerName = data.val().CustomerName;
var AmountSent = data.val().AmountSent;
var TimeEffected= data.val().TimeEffected;
var DateEffected = data.val().DateEffected;
var Successful = data.val().Successful;
content += '<tr>';
content += '<td>' + CustomerName + '</td>';//column2
content += '<td>' + AmountSent + '</td>'; //column1
content += '<td>' + TimeEffected + '</td>'; //column1
content += '<td>' + DateEffected + '</td>'; //column1
content += '<td>' + Successful + '</td>'; //column1
content += '</tr>';
});
$('#ex-table').append(content);
When it 'was database.once' and I had a refresh button I wouldn't get the data duplicated but I've changed it to'database.on' and now the data in the table duplicates whenever I do anything to the database.
I'm looking for the most cost-effective way. I'm not sure which one of both 'database.once' or 'database.on' save money.
回答1:
Since you listen to the value event on transactions, each time your callback is called the snapshot will contain all data under transactions. So any data that wasn't changed will also be in the snapshot, leading to it being in your table multiple times.
I see two options:
- Wipe the table each time you get updated data
- Perform more fine-grained updates
Wipe the table each time you get updated data
This is the simplest, since it requires the fewest changes to your existing code. Just clear the contents from the table whenever you get updated data from the database:
var database = firebase.database().ref().child('transactions');
database.on('value', function(snapshot){
$('#ex-table').empty(); // clear existing contents
if(snapshot.exists()){
var content = '';
snapshot.forEach(function(data){
var CustomerName = data.val().CustomerName;
var AmountSent = data.val().AmountSent;
var TimeEffected= data.val().TimeEffected;
var DateEffected = data.val().DateEffected;
var Successful = data.val().Successful;
content += '<tr>';
content += '<td>' + CustomerName + '</td>';//column2
content += '<td>' + AmountSent + '</td>'; //column1
content += '<td>' + TimeEffected + '</td>'; //column1
content += '<td>' + DateEffected + '</td>'; //column1
content += '<td>' + Successful + '</td>'; //column1
content += '</tr>';
});
$('#ex-table').append(content);
This should work fine, but repaints the entire table contents every time anything in there changes. This may result in noticeable flicker when the table is large.
Perform more fine-grained updates
The alternative is to perform more fine-grained updates. I.e. initially you add all children, after that you only add the new children, remove any data that gets removed from the database, etc.
Firebase has specific events for this purpose, which fire one level lower in the database. For example, the child_added event is defined as "fires initially for each node under the reference, and then each time a node is added under the reference". In the same vein there are child_removed, child_changed and child_moved events. With these events you can perform more granular updates to the table.
For example, here's how you'd handle child_added:
var database = firebase.database().ref().child('transactions');
database.on('child_added', function(snapshot){
var data = snapshot.val();
var content = '<tr id="'+snapshot.key+'">';
content += '<td>' + data.CustomerName + '</td>';
content += '<td>' + data.AmountSent + '</td>';
content += '<td>' + data.TimeEffected + '</td>';
content += '<td>' + data.DateEffected + '</td>';
content += '<td>' + data.Successful + '</td>';
content += '</tr>';
$('#ex-table').append(content);
});
Aside from cleaning up the code a bit, I also add the snapshot.key to the tr. This allows you to later look up the row for a key, just in case you get a child_changed, or child_removed event.
For example, here's how to remove the row from the table when it gets removed from the database:
database.on('child_removed', function(snapshot){
$('#'+snapshot.key).remove()
});
来源:https://stackoverflow.com/questions/54273175/how-to-check-if-data-is-already-in-html-table-using-firebase-real-time-database