2

After some research, I understand the most accurate way to create a timer in Javascript is to compare the elapsed time from a starting point using date.now() -as this answer suggests.

var startTime = Date.now();

var interval = setInterval(function() {
  var elapsedTime = Date.now() - startTime;
  var time = (elapsedTime / 1000).toFixed(3);
  console.log(time);
}, 10);

This provides the accuracy I am looking for, but I am looking to make this timer reset itself after a certain value (let's say var total = 12000). This value is determined by the length of a video playlist (I am building a 'live' playhead for a video program) and is a variable.

I'm stuck how to go about this, as the counter is counting elapsed time from a certain point in time, it doesn't quite fit the logic of what I am looking for. Any suggestions would be appreciated.

ogot
  • 341
  • 2
  • 17
  • Wrap it in another setInterval that clears and resets the inner interval – bryan60 Jan 22 '20 at 13:59
  • I've tried that and it only starts the counter after a delay (in this case 3000ms): var startTime = Date.now(); setInterval(function() { var interval = setInterval(function() { var elapsedTime = Date.now() - startTime; var time = (elapsedTime / 1000).toFixed(3); console.log(time); }, 10); }, 3000); – ogot Jan 22 '20 at 14:03
  • 1
    you can't, the end. The JS spec itself explains why, but the tl;dr is that setTimeout does not have 1ms resolution. It will give you ~1ms for a few calls and will then drastically [throttle to ~4ms instead](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified). But it sounds like you don't need a 1-after-1 ms timer at all, you just need ms-accuracter _interval measurement_, which `Date.now()` already lets you do. – Mike 'Pomax' Kamermans Jan 22 '20 at 14:06
  • correct -- an interval measurement which I need to reset after a certain value. – ogot Jan 22 '20 at 14:09
  • 1
    `var elapsedTime = (Date.now() - startTime) % playListLength;` ... and then you dont need any other special coding. ... A question: But how can you guarantee *ahead of time* when to "reset" as @Mike'Pomax'Kamermans mentions, the resolution is not exact. – GetSet Jan 22 '20 at 14:14
  • I thought about this solution and it's great in its simplicity -- but there is a crucial problem: if the playlist length increases (a video is added) while a person is watching, it means the live time will suddenly jump in value as the modulo value increases. I want to avoid this behaviour as it disrupts the live time for viewers. – ogot Jan 22 '20 at 14:22

2 Answers2

2

You could use a .setTimeout() at the end of your code to restart your .setInterval(), after the desired time has passed

function runInterval (loopAfter) {
  var startTime = Date.now();

  var interval = setInterval(function() {
    var elapsedTime = Date.now() - startTime;
    var time = (elapsedTime / 1000).toFixed(3);
    console.log(time);
  }, 10);
  
  setTimeout(() => {
    clearInterval(interval);
    runInterval(loopAfter);
  }, loopAfter);
}

runInterval(5000);
Shiny
  • 4,945
  • 3
  • 17
  • 33
0

Try this:

var startTime = Date.now();
let total = 0;
var interval = setInterval(function() {
  if (total === 12000) {
    total = 0;
    startTime = Date.now();
  } else {
    total++;
    var elapsedTime = Date.now() - startTime;
    var time = (elapsedTime / 1000).toFixed(3);
  }
  console.log(time);
}, 10);
Raghu Chahar
  • 1,637
  • 2
  • 15
  • 33