Page refresh when there is no activity (cont..)

I am using the following function (with the help of ScallioXTX) to refresh a page when there is no activity:


(function() {
    var timeout;
 
    $(function() {
        startRefresh();
    });
 
    function startRefresh() {
        clearTimeout(timeout); // stop previous timeout
        timeout = setTimeout(startRefresh, 30000);
        $.get('test.php', function(data) {
            $('#content').html(data);    
        });
    }
 
    $(body).on('mousemove keydown', function() {
        startRefresh(); // restart timeout
    });
}());

But for some reason it is refreshing the page even when I am typing in a text area during those 30 seconds

Remove the parts that relate to setting a timeout and interaction, and the cause of the problem becomes clear.


(function() {
    $(function() {
        startRefresh();
    });

    function startRefresh() {
        $.get('test.php', function(data) {
            $('#content').html(data);
        });
    }
}());

It’s an endless loop. What you may want to look in to doing instead is to have a separate resetTimer function where the setTimeout parts occur, so that from the startRefresh function you can call that resetTimer as well.

Hi Paul. Thanks for the reply. Let me first say that this was the original function:


$(function() {
    startRefresh();
});

function startRefresh() {
    setTimeout(startRefresh,30000);
    $.get('test.php', function(data) {
        $('#content').html(data);
    });
}

So right now I just did what you suggested and removed the parts that are relating to setting a timeout and interaction. But I don’t see the problems?

So what do I need to adjust to make this work?

Let’s take this a step at a time.

When the page loads, you want the timer to start. When it triggers you want to update Content


$(function() {
    startRefresh();
});

function startRefresh() {
    setTimeout(function () {
        $.get('test.php', function(data) {
            $('#content').html(data);    
        });
    }, 30000);
}

The next part is the challenging one, for when the timeout triggers you want to set up another timer. You don’t want to have both the timer setup and the page updating occurring at the same time, for then you have the same troubles that you currently have. We can’t do that easily at this stage, but as Martin Fowler and Kent Beck said:

When you find you have to add a feature to a program, and the program’s code is not structured in a convenient way to add the feature, first refactor the program to make it easy to add the feature, then add the feature.

Let’s refactor the code so that it’s all encapsulated in the anonymous function, and extract out the different behaviours to separate functions. After we’ve done that we can then add in the feature to trigger another timer.


$(function () {
    function updateContent() {
        $.get('test.php', function (data) {
            $('#content').html(data);
        });
    }
    function startRefresh() {
        setTimeout(updateContent, 30000);
    }

    startRefresh();
});

From within the new updateContent we’re wanting to set a new timer, so startRefresh is now the wrong function name. We can rename that function to resetTimer and add some code to assign the timer to a variable, so that we can then reset things based on that.


$(function () {
    var timer,
        updateContent;

    function resetTimer() {
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(updateContent, 30000);
    }

    updateContent = function updateContent() {
        resetTimer();
        $.get('test.php', function (data) {
            $('#content').html(data);
        });
    }

    resetTimer();
});

Because the updateContent function calls the resetTimer one, it really should be defined after it. By declaring updateContent as an inline expression we can help to ensure that the function isn’t declared out of turn.

Now the code is ready to let us reset the timer from within the updateContent function, and we can also reset it when activity occurs too.


$(function () {
    var timer,
        updateContent;

    function resetTimer() {
        if (timer) {
            window.clearTimeout(timer);
        }
        timer = window.setTimeout(updateContent, 30000);
    }

    updateContent = function () {
        resetTimer();
        $.get('test.php', function (data) {
            $('#content').html(data);
        });
    };
    resetTimer();
    $(document.body).on('mousemove keydown', resetTimer);
});

Hi Paul. This works brilliantly, and your explanation is very clear and straightforward :tup: I have one last question. The content should be initially loading, now it is loading after the first 30 seconds. What should I adjust to make it load when I land on the page and that after that the function is doing its work?

The resetTimer() near the end can be replaced with updateContent()

Hi Paul that did the trick indeed, :slight_smile: thank you so much