PMint PMint - 6 months ago 34
jQuery Question

Only append new data

I'm trying to make a log parser, that updates the log every 10 seconds. It's mostly functional, but when I try to update it, it just appends the whole log again, instead of just the new data.

My Javascript:

$(document).ready(function() {

var data;
var lines;

$.ajax({
async: false,
type: 'GET',
url: 'test.log',
success: function(log) {\
data = log;
lines = data.split("\n");
console.log("Received log");
}
});

function updateLog()
{
$.ajax({
async: false,
type: 'GET',
url: 'test.log',
success: function(log) {
data = log.replace(data, "");
lines = log.split("\n");

console.log("Received log");
}
});

$.each(lines, function(n, elem)
{
$('#text').append('<div>' + elem + '</div>');
});
}



$.each(lines, function(n, elem)
{
$('#text').append('<div>' + elem + '</div>');
});


setInterval(function(){updateLog();}, 10000);
});


Example test.log content:

Hello
How are you?


But instead of it only adding potential new lines, it just copies the whole thing even though I think it shouldn't happen because of the
replace
, which is supposed to take the old
data
and change it into
''
in the new data (only leaving new lines).

Answer

It looks to me like you save only the new part of last request to data, so you are actually only replacing the part of the log that was new the last time you updated the log by an empty string. Moreover, you are not using data but log (which is the full log) to compute lines, and are appending all the lines in lines to your div.

I think something like this should work:

$(document).ready(function() {
    var processed_data = '';
    function updateLog() {
        $.ajax({
            async: false,
            type: 'GET',
            url: 'test.log',
            success: function(log) {
                var new_data = log.replace(processed_data, '');
                processed_data = log;
                console.log("Received log");
                var lines = new_data.split('\n');
                $.each(lines, function(n, elem) {
                   $('#text').append('<div>' + elem + '</div>');
                });
            }
        });
    }
    updateLog();
    setInterval(function(){updateLog();}, 10000);
}); 

Note that I also got rid of some of the code duplication that was in your example by just calling updateLog() on load instead of copying its contents.

It would also probably be more efficient to just keep track of the length of the part of the log that is already printed. Something like this:

$(document).ready(function() {
    var processed_data_length = 0;
    function updateLog() {
        $.ajax({
            async: false,
            type: 'GET',
            url: 'test.log',
            success: function(log) {
                var new_data = log.substring(processed_data_length, log.length);
                processed_data_length = log.length + 1;
                console.log("Received log");

                $.each(lines, function(n, elem) {
                   $('#text').append('<div>' + elem + '</div>');
                });
            }
        });
    }
    updateLog();
    setInterval(function(){updateLog();}, 10000);
});