1

I have countdown timer running on web and second function that periodically check changes in database, but it's more important to check it more often (let's say every 3 seconds) when timer is coming to an end and less often when timer starts. I have following code:

var days, hours, minutes, seconds, check_interval; 

setInterval(function() {

    var current_date = new Date().getTime();
    var seconds_left = (date_end - current_date) / 1000;

    days = parseInt(seconds_left / 86400);
    seconds_left = seconds_left % 86400;

    hours = parseInt(seconds_left / 3600);
    seconds_left = seconds_left % 3600;

    minutes = parseInt(seconds_left / 60);
    seconds = parseInt(seconds_left % 60);

    document.getElementById('countdown').innerHTML = days + 'd ' + hours + 'h ' + minutes + 'm ' + seconds + 's';


    if (hours > 0) {
        check_interval = 60000;
    } else if (hours = 0 && minutes > 5) {
        check_interval = 10000;
    } else {
        check_interval = 3000;
    }


    var check_bids = setInterval(function() {
        $.ajax({
            type: 'POST',
            url: '/check.class.php',
            dataType: 'json',
            data: { ... }
        }).done(function(response) {
            ...
        }).fail(function(jqXHR, textStatus, errorThrown) {
            console.log('Bids check failed: '+textStatus, errorThrown);
        });
    }, check_interval); // Accelerating interval

}, 1000);

It works as I want but I'm really not sure if I can combine these two setInteval functions like that? Is it effective at all? Thanks for advice.

UPDATE:

Thanks to Strille, I finally choose this simple solution with only one setInterval:

var days, hours, minutes, seconds; 

setInterval(function() {

    var current_date = new Date().getTime();
    var seconds_left = seconds_to_end = (date_end - current_date) / 1000;

    days = parseInt(seconds_left / 86400);
    seconds_left = seconds_left % 86400;

    hours = parseInt(seconds_left / 3600);
    seconds_left = seconds_left % 3600;

    minutes = parseInt(seconds_left / 60);
    seconds = parseInt(seconds_left % 60);

    document.getElementById('countdown').innerHTML = days + 'd ' + hours + 'h ' + minutes + 'm ' + seconds + 's';


    if (hours > 0) { // If time to end is greater than 1 hour repeat ajax call every 60 seconds etc.
        repeat_every_x_seconds = 60;
    } else if (minutes > 5) {
        repeat_every_x_seconds = 10;
    } else {
        repeat_every_x_seconds = 3;
    }

    if (parseInt(seconds_to_end) % repeat_every_x_seconds == 0) {
        check(); // Call this function every x seconds.
    }
}, 1000);



var check = function() {
    $.ajax({
        type: 'POST',
        url: '/check.class.php',
        dataType: 'json',
        data: { ... }
    }).done(function(response) {
        ...
    }).fail(function(jqXHR, textStatus, errorThrown) {
        ...
    });
};

Maybe it helps somebody. And sorry for english :)

hovado
  • 4,474
  • 1
  • 24
  • 30
  • 3
    You need to cancel the old `setInterval` with `clearInterval`, and start a new one with the new repetition rate. – Barmar Dec 10 '14 at 20:46
  • 12
    use `setTimeout` instead of `setInterval`. And recall it inside the function. – Yoshi Dec 10 '14 at 20:46
  • Thanks @Yoshi. I'm just worried that ajax call could sometimes lasts more than 1 second. Is using of setTimeout somehow "safer" than Strille's solution? – hovado Dec 10 '14 at 22:09

1 Answers1

0

Since you already need to run some code every second to update the text, you could simply have a check every second in the same setInterval if enough time has passed for a new ajax call to be made. We just need to add a variable last_checked_date which stores the time we last made the ajax call:

var days, hours, minutes, seconds, check_interval, last_checked_date = 0;

setInterval(function() {

    ... 

    if (hours > 0) {
        check_interval = 60000;
    } else if (hours = 0 && minutes > 5) {
        check_interval = 10000;
    } else {
        check_interval = 3000;
    }

    if (current_date - last_checked_date > check_interval) {
        // do ajax call

        last_checked_date = current_date;
    }

}, 1000);
Strille
  • 5,741
  • 2
  • 26
  • 40
  • `current_date` in my case is updated every second so it should be `if (date_end - last_checked_date > check_interval)` because `date_end` is fixed time for timer end, but this solution is really simplest. What happens when ajax call last more then 1 second? – hovado Dec 10 '14 at 21:57
  • Yes, since `current_date` is updated every second `current_date - last_checked_date` will increase each time setInterval triggers, and if the difference is larger than `check_interval` it's time to run the ajax. So I think my example is correct. If the ajax call takes more than one second is not really a problem, but it would probably be a good idea to not call ajax again if a request is already in progress. – Strille Dec 11 '14 at 10:31