Tyler
Tyler

Reputation: 874

jQuery Running Several Dynamically Created Timers

What I Am Trying To Achieve

My site has multiple crons to fetch external data for site members game information. This page I am creating shows the last fetched data scope, time and what I am trying to implement, a countdown timer until the next fetch.

  1. Page Load
  2. Timers Start
  3. Timer Ends
  4. Timer Text: Fetching Data...
  5. Timer restarts

Problems I Am Having

Working with one timer has been fairly easy, however this page needs several dozen and thus dynamic timer names to stop / start and whatnot. This is a somewhat basic version to answer this question upon having several timers running this way, hence the 30, 60, 90 and 120 intervals.


My jQuery Timer - Working

>> View On CodePen <<

var timer = 20;

var interval = setInterval(function() {
    timer--;

    var H  = Math.floor((timer % (60 * 60 * 24)) / (60 * 60));
    var HH = (H < 9 ? "0" : "") + H;
    var M  = Math.floor((timer % (60 * 60)) / 60);
    var MM = (M < 9 ? "0" : "") + M;
    var S  = Math.floor(timer % 60);
    var SS = (S < 9 ? "0" : "") + S;

    $('.timer').text(HH + ":" + MM + ":" + SS);
    if (timer === 0) clearInterval(interval);
}, 1000);

Multiple Timer Attempt

>> View on CodePen <<

$('.timer').each(function(){
    var timer_interval = $(this).data("interval");
    var timer_name = $(this).data("timer-name");
    startTimer(timer_name, timer_interval);
});
function startTimer(name, interval) {
    var name = setInterval(function() {
        timer--;
        var H  = Math.floor((interval % (60 * 60 * 24)) / (60 * 60));
        var HH = (H < 9 ? "0" : "") + H;
        var M  = Math.floor((interval % (60 * 60)) / 60);
        var MM = (M < 9 ? "0" : "") + M;
        var S  = Math.floor(interval % 60);
        var SS = (S < 9 ? "0" : "") + S;

        $('.timer').text(HH + ":" + MM + ":" + SS);
        if (timer === 0) {
          $('.timer').text("Updating");
          clearInterval(name);
        }
    }, 1000);
}

Questions

  1. How can I run several timers with dynamically created names?
  2. Upon a timer reaching 0, how can I check which timer has stopped to then pass back through the loop to restart?

Upvotes: 0

Views: 1243

Answers (2)

guest271314
guest271314

Reputation: 1

You can use .queue() to provide a queueName to one or more functions to call in sequence, or not in sequence; .promise(), .then() to provide reschedule the function to be called again when all of the functions in queueName array have been called.

function startTimer(queueName, interval, el, next) {
  var timer = interval;
  $(el).data(queueName, setInterval(function() {
    timer--;
    var H = Math.floor((timer % (60 * 60 * 24)) / (60 * 60));
    var HH = (H < 9 ? "0" : "") + H;
    var M = Math.floor((timer % (60 * 60)) / 60);
    var MM = (M < 9 ? "0" : "") + M;
    var S = Math.floor(timer % 60);
    var SS = (S < 9 ? "0" : "") + S;

    $(el).text(HH + ":" + MM + ":" + SS);
    if (timer === 0) {
      $(el).text("Updating");
      clearInterval($(el).data(queueName));
      next();
    }
  }, 1000));
}

function scheduleTimer(elem) {
  return $.when.apply($,
    $.map(elem ? elem : $(".timer"), function(el, index) {
      var timer_interval = $(el).data("interval");
      var timer_name = $(el).data("timer-name");
      return $(el).queue(timer_name, function(next) {
          startTimer(timer_name, timer_interval, el, next)
        }).dequeue(timer_name).promise(timer_name)
        .then(function(el) {
          var timer_name = el.data("timer-name")
          return el.delay(2000, timer_name)
            .queue(timer_name, function(next) {
              scheduleTimer(el)
            }).dequeue(timer_name).promise(timer_name)
        })
    }))
}

scheduleTimer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div data-interval="30" data-timer-name="Timer1" class="timer">00:00:00</div>
<div data-interval="60" data-timer-name="Timer2" class="timer">00:00:00</div>
<div data-interval="90" data-timer-name="Timer3" class="timer">00:00:00</div>
<div data-interval="120" data-timer-name="Timer4" class="timer">00:00:00</div>

Upvotes: 1

lloyd
lloyd

Reputation: 1181

I think Timer was undefined in the startTimer function and needed to be renamed. Let me know if this is the functionality you're looking for. Judging by how its currently working on my end, you will need an Id for each timer. I will update my answer when possible if still needed.

$('.timer').each(function(){
    var timer_interval = $(this).data("interval");
    var timer_name = $(this).data("timer-name");
    startTimer(timer_name, timer_interval);
});
function startTimer(name, interval) {
    var name = setInterval(function() {
        interval--;
        var H  = Math.floor((interval % (60 * 60 * 24)) / (60 * 60));
        var HH = (H < 9 ? "0" : "") + H;
        var M  = Math.floor((interval % (60 * 60)) / 60);
        var MM = (M < 9 ? "0" : "") + M;
        var S  = Math.floor(interval % 60);
        var SS = (S < 9 ? "0" : "") + S;

        $('.timer').text(HH + ":" + MM + ":" + SS);
        if (interval === 0) {
          $('.timer').text("Updating");
          clearInterval(name);
        }
    }, 1000);
}

Upvotes: 1

Related Questions