Stop and restart setInterval function

Asked

Viewed 4,345 times

4

I have a javascript function that starts a chronometer. I want to be able to stop, and start again (reset).

example jsfiddle: http://jsfiddle.net/fk2unkb9/2/

var countms = 0;

function start() {
    var counterms = setInterval(function () {
        countms = countms + 1;
        var id_label_ms = document.getElementById("count_label_ms");
        id_label_ms.innerHTML = countms / 100 + " s";
    }, 1);
}

function stop() {
    clearInterval(counterms);
}

4 answers

5


Your idea is on the right track. You have to put the counterms in a common scope for you to use clearInterval(counterms).

I also suggest you withdraw var id_label_ms = document.getElementById("count_label_ms"); out of the setInverval not to weigh in performance. This element needs only once, not every 10 milliseconds.

I have put together other ideas, some suggested in the comments here.

window.onload = function () {
    var countms = 0;
    var counterms;
    var id_label_ms = document.getElementById("count_label_ms");
    var cronometro = {};
    var ativo = false;

    cronometro.start = function () {
        if (ativo) return;
        ativo = true;
        counterms = setInterval(function () {
            countms = countms + 1;
            id_label_ms.innerHTML = countms / 100 + " s";
        }, 10);
    };

    cronometro.stop = function () {
        clearInterval(counterms);
        ativo = false;
    };

    cronometro.reset = function () {
        cronometro.stop();
        ativo = false;
        id_label_ms.innerHTML = countms = 0;
    };

    ['start', 'stop', 'reset'].forEach(function (tipo) {
        var input = document.querySelector('input[name="' + tipo + '"]');
        input.addEventListener('click', cronometro[tipo]);
    });
};

jsFiddle: http://jsfiddle.net/uj7vr2z7/1/

  • Thanks @Rgio and how can I restart from 0 (reset) ?

  • @akm I joined now.

  • it would not be better to put the var id_label_ms = document.getElementById("count_label_ms"); out of methods, so you don’t have to look for him?

  • @Tobymosque yes, it would be better. I wanted to give an example with addeventlistener with closed scope but I had to leave and put later.

  • @Sergio would also be interesting to lock the start button when the timer is running so as not to bug the team

  • @Marcelobonifazio good idea, joined in my new version.

  • @Tobymosque I have now joined a version that pleases me more :)

  • Who gave the -1 can comment. I always thank anyone who points out mistakes and like to discuss different ideas.

  • @Sergio, your method is not working continuously. the buttons seem to change behavior. After a few clicks it just stopped working and became infinite.

  • @Sergio, if you click start, then reset, and click start it stops working.

  • @Ivanferrer thanks, had a bug from the previous version. The stop(); should be cronometro.stop();. Corrected.

  • got better now.

Show 7 more comments

2

I modified the code to continue using your same idea.

var countms = 0;

var teste;

    var counterms = function() {
    teste = setInterval(function () {
        countms = countms + 1;
        var id_label_ms = document.getElementById("count_label_ms");
        id_label_ms.innerHTML = countms / 100 + " s";
    }, 1);
    }

function start() {
    counterms();
}

function stop() {
    clearInterval(teste);
}

function reset(){
    clearInterval(teste);

    var id_label_ms = document.getElementById("count_label_ms");
    id_label_ms.innerHTML = 0;
}

HTML

<label id=count_label_ms></label>
<br>
<p>
    <input type=button value="stop" onclick="stop()" />
    <input type=button value="reset" onclick="reset()" />
    <input type=button value="start" onclick="start()" />
</p>

2

In my view the only problem of the proposed solution is that the setInterval chronometer is rescheduled at the end of the execution, so if the interval is set to 10ms and the time calculation and the label update takes 1ms, then every 10ms the timer will delay 1ms.

so I altered Sergio’s fiddle to make this difference more perceptible:

window.addEventListener("load", function() {
  var count_label_tm = document.getElementById("count_label_tm");
  var count_label_ms = document.getElementById("count_label_ms");

  var btStop = document.getElementById("btStop");
  var btReset = document.getElementById("btReset");
  var btStart = document.getElementById("btStart");

  var dtStart;
  var dtAtual;
  var tmAtual = new Date(0);
  var tmAcumulado = new Date(0);

  var interval = 6;
  var countms = 0;
  var counterms;

  btStop.disabled = true;
  btReset.disabled = true;
  btStart.disabled = false;

  btStart.addEventListener("click", function() {
    btStop.disabled = false;
    btReset.disabled = false;
    btStart.disabled = true;
    
    dtStart = new Date();
    counterms = setInterval(function () {
      countms = countms + interval;
      atualizarInputs();
    }, interval);
  });

  btStop.addEventListener("click", function() {
    btStop.disabled = true;
    btReset.disabled = false;
    btStart.disabled = false;
    
    clearInterval(counterms);
    atualizarInputs();
    tmAcumulado = tmAtual;
  });

  btReset.addEventListener("click", function() {   
    btStop.disabled = true;
    btReset.disabled = true;
    btStart.disabled = false;
    
    countms = 0;
    dtStart = null;
    dtAtual = null;
    tmAtual = new Date(0);
    tmAcumulado = new Date(0);
    
    count_label_ms.innerHTML = '';
    count_label_tm.innerHTML = '';
  });

  function atualizarInputs() {
    dtAtual = new Date();
    tmAtual = new Date(tmAcumulado.getTime() + dtAtual.getTime() - dtStart.getTime());
    setHTML();
  } 


  function setHTML() {
    //usando um contador para registrar os ms
    count_label_ms.innerHTML = formatData(new Date(countms));

    //calculando o tempo gasto usando como base a data de inicio, o tempo acumulado e a data atual.
    count_label_tm.innerHTML = formatData(tmAtual);
  }

  function formatData(time) {
    hours = time.getUTCHours().toString();
    minutes = time.getUTCMinutes().toString();
    seconds = time.getUTCSeconds().toString();
    milliseconds = time.getUTCMilliseconds().toString();

    return "00".substring(0, 2 - hours.length) + hours + ":" +
      "00".substring(0, 2 - minutes.length) + minutes + ":" +
      "00".substring(0, 2 - seconds.length) + seconds + "." +
      "000".substring(0, 3 - milliseconds.length) + milliseconds;
  }
});
<div>
  Count: <label id="count_label_ms"></label>
</div>
<div>
  Datas: <label id="count_label_tm"></label>
</div>
<div>
  <input id="btStop" type=button value="stop" />
  <input id="btReset" type=button value="reset" />
  <input id="btStart" type=button value="start" />
</div>

It is true that the time required to perform the function of serInterval increased due to the increased complexity, but this helps to demonstrate the difference between the two approaches.

  • the problem in using Data instead of Count is that it always takes the current team, ie the stop does not work exactly as it should

2

To do this, you need to create a variable that transports between methods and always allows you to return the origins:

var countms = 0;
var intervalTxt = null;
function start() {
    var id_label_ms = document.getElementById("count_label_ms");
    if (intervalTxt == null) {
        intervalTxt = setInterval(function() {
            countms = countms + 1;
            id_label_ms.innerHTML =  countms / 100 + " s";
        }, 1);
    }
}

function stop() {
    if (intervalTxt != null) {
        var id_label_ms = document.getElementById("count_label_ms");
        clearInterval(intervalTxt);
        intervalTxt = null;
        id_label_ms.innerHTML =  countms / 100 + " s";
    }
}

function reset() {
    var id_label_ms = document.getElementById("count_label_ms");
    clearInterval(intervalTxt);
    intervalTxt = null;
    id_label_ms.innerHTML = 0 + " s";
}

function resetContinuo() {
    var id_label_ms = document.getElementById("count_label_ms");
    clearInterval(intervalTxt);
    intervalTxt = null;
    countms = 0;
    id_label_ms.innerHTML = 0 + " s";
    start();
}

Here an example: http://jsfiddle.net/fk2unkb9/9/
Or if you want something more interesting using object: http://jsfiddle.net/fk2unkb9/20/
And here’s a more elaborate example: http://jsfiddle.net/fk2unkb9/23/

  • A hint, in jsfiddle you can use the following key combination to indent the current code text: [Alt] + [A] > [Shift] + [Tab]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.