Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recommendation for multiple ajax countdown timers (call per second)

I'm creating a system that has 100 count down timers. Each timer makes an ajax call every second to get the endTime in the database and update the countdown time. I need to call this every second because the endTime can change. The system is currently working but its incredibly slow, and I'm curious if there is a better way than to call 100 ajax calls every second.

var countDownDate;
    var is_locked;
    var interval = 1000;

    function update_timer() {
      $.ajax({
        type: 'POST',
        url: '<?php echo base_url('/Timer/getTimer');?>',
        data: {
          id: <?php echo $lane->id; ?>,
        },
        async: false,
        dataType: 'json',
        success: function (response) {
          var image_url = null;
          $.each(response, function(k, v) {
            if (k == 'end_time') {
              countDownDate = new Date(v).getTime();
            }
            if (k == 'is_locked') {
              is_locked = v;
              if (is_locked == 1) {
                $('.myButton').prop('disabled', true);
              } else {
                $('.myButton').prop('disabled', false);
              }
            }
          })
          // Get today's date and time
          var now = new Date().getTime();

          // Find the distance between now and the count down date
          var distance = countDownDate - now;
          // Time calculations for days, hours, minutes and seconds
          var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
          var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
          var seconds = Math.floor((distance % (1000 * 60)) / 1000);

          // Display the result in the element with id="demo"
          document.getElementById("demo").innerHTML =  hours + "h "
            + minutes + "m " + seconds + "s ";

          // If the count down is finished, write some text
          if (distance < 0) {
            //clearInterval(x);
            document.getElementById("demo").innerHTML = "EXPIRED";
          }
        },
        complete: function (data) {
          // Schedule the next
          setTimeout(update_timer, interval);
        }
      });
    }
    update_timer;
    setTimeout(update_timer, interval);
like image 716
Travis Cornelius Avatar asked Dec 12 '25 14:12

Travis Cornelius


1 Answers

Websockets is the clean and beautiful solution for this situation as commented by @CertainPerformance

How about this workaround as suggested by @Thum Choon Tat

instead of let every one of the 100 timers make a request every 1 second to get his own endTime (100 requests a second), make only 1 request every second and get all the endtimes of all the timers.

This is my plan

  • We will use localStorage to share the data between all the tabs. and save these items in it:

    1. lastRequeted The the last time any HTML page made the request.
    2. requesterId the Id of the page that is responsible for firing the Ajax requests
    3. timerId1 , timerId2 , timerId3 , .... will hold the endTimes for every timer
  • Any page having one or more timer from the 100 timers can request the endTimes of all the timers, and set the lastRequeted value to now, and set requesterId to it's Id

  • We run an interval on the client side every second to check lastRequeted , if it is too old " like 4 seconds ago" , it will do the request, if it's new then it get's the data it needs from timerIdX items.
  • only one HTML page will register it self as the requesterId no other HTMl page will do requests unless the data is too old

This is the JS code you will use on any HTML that has a timer

var requesterId = Math.random(); // random Id for this page

setInterval(function (){
    var ts = Math.floor(Date.now() / 1000);
    var lastRequested = localStorage.getItem('lastRequested');
    var currentRequester = localStorage.getItem('requesterId');

    if (requesterId == currentRequester ||  (ts - lastRequested > 4)){
        // if I'm the current requester or the last requested time is older than 4 seconds, I will do the request
        localStorage.settItem('requesterId', requesterId);
        $.ajax({
        type: 'POST',
        url: '/Timer/getAllTimers',
        dataType: 'json',
        success: function(data){
             localStorage.setItem('lastRequested', Math.floor(Date.now() / 1000));
             for (var i =0; i < data.length; i++){
                 var timerId = data[i].timerId;
                 var timerEndTime = data[i].timerEndTime;
                 localStorage.setItem(timerId, timerEndTime);
             }
             updateTimersEndTimes();
        }
    } else {
        // the data is updated I will get the timer endTime
        updateTimersEndTimes();

    }
}, 1000);

/**
 * update timers endTimes from the localStorage
*/
function updateTimersEndTimes()
{
     /*
      // pseudo code
      $("Div#timersOnPage .timer").each(function(){
          var timerId = $(this).data("timerId");
          var timerEndtime = LocalStorage.getItem(timerId);
          $(this).data('timerEndTime', timerEndtime);
     });

     */
}

On the server you will send the endTime for all the timers

/Timer/getAllTimers

<?php
//buid the array from your database
$timersArray = [];
for ($i = 0; $i < 100; $i++){
    $timer = new stdClass();
    $timer->timerId = $i;
    $timer->timerEndTime = "2019-08-23 05:02:23";//changes for every timer
    $timersArray[] = $timer;
}

header('Content-Type: application/json');
echo json_encode($timersArray);
exit;

Now every HTML that has a timer will not fire a request, however it will check every second if the timers data is updated, then it will use it.

like image 200
Accountant م Avatar answered Dec 15 '25 05:12

Accountant م



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!