clearTimeout not working properly

Posted on
  • I created a LED dimming function (source code). It does what I expect it to do every DURATION miliseconds, with an exception. I added two console logs to highlight the problem, this is the line which does not work, clearInterval(stepInterval), logging ERROR: Unknown Interval.
    All the other clearIntervals seem to be working. Here is some sample output from the script:

    run to 1
    clearing stepInterval number 11
    ERROR: Unknown Interval
    should have cleared stepInterval number 11
    done 1.
    done 0.99
    run to 0
    clearing stepInterval number 13
    ERROR: Unknown Interval
    should have cleared stepInterval number 13
    done -0.
    done 0.01
    run to 1
    clearing stepInterval number 15
    ERROR: Unknown Interval
    should have cleared stepInterval number 15
    done 1.
    done 0.99
    run to 0
    clearing stepInterval number 17
    ERROR: Unknown Interval
    should have cleared stepInterval number 17
    done -0.
    done 0.01
    run to 1
    clearing stepInterval number 19
    ERROR: Unknown Interval
    should have cleared stepInterval number 19
    

    So the intervals keep adding up, I assume it will either run out of memory or gray dragons will come out of the espruino board.

    Any hints?

  • Hi,

    What do you mean by // Workaround for clear fail in the comments? Are you expecting clearInterval to reset the variable passed into it? I'm afraid that doesn't happen (in Espruino or in other JS interpreters).

    That means that if you're doing if (foo!==undefined) clearInterval(foo); you need to be writing if (foo!==undefined) { clearInterval(foo); foo=undefined; }, or next time around the loop it'll try and clear the interval that has already been cleared.

    Simply doing that in your code fixes it:

    var DURATION = 2000;
     
    function sign(num) {
      return Math.round(Math.abs(num) / num);
    }
     
    function round(num, decimals) {
      return (Math.round(num * Math.pow(10, decimals))) / Math.pow(10, decimals);
    }
     
    var currentIntensity = 0;
    var interval;
    var stepInterval;
     
    function dim(intensity, time, steps, cb) {
      console.log('run to', intensity);
      if (typeof intensity == 'undefined') intensity = 0;
      if (typeof time == 'undefined') time = 1000;
      if (typeof steps == 'undefined') steps = 100;
      var freq = time/steps;
     
      var intensityStep = round((intensity - currentIntensity) / steps, 2);
      var signStep = sign(intensityStep);
      intensityStep = Math.abs(intensityStep);
     
      if (typeof stepInterval != 'undefined') {
        console.log('clearing stepInterval', typeof stepInterval, stepInterval);
        clearInterval(stepInterval);
        console.log('should have cleared stepInterval', typeof stepInterval, stepInterval);
        // Workaround for clear fail
        stepInterval = undefined;
      }
     
      stepInterval = setInterval(function() {
        currentIntensity = currentIntensity + (intensityStep * signStep);
        if (sign(intensity - currentIntensity) != signStep) {
          console.log('done', currentIntensity);
          currentIntensity = currentIntensity - (intensityStep * signStep);
          console.log('done', currentIntensity);
          clearInterval(stepInterval);
          stepInterval = undefined;
          if (typeof cb !== 'undefined') cb();
        }
        if (typeof interval !== 'undefined') {
          clearInterval(interval);
          interval = undefined;
        }
        interval = setInterval(function() {
          digitalPulse(LED1, 1, Math.abs(currentIntensity * 10));
        }, 10);
      }, freq);
    }
     
    var self = this;
    function callback() {
      return dim(Math.round(currentIntensity) === 0 ? 1 : 0, DURATION, 100, callback);
    }
     
    dim(1, DURATION, 100, callback);
    

    Personally I'd just check for undefined with !== undefined too - it's easier to write and a bit quicker.

  • Later edit: I see what you mean, thanks for the clarification. I expected the setInterval integer values to be reused like the setWatch values are, and when I saw them rising to infinity I assumed something was wrong :)

  • Espruino just makes the intervals one more than the last one in the list (it's faster/easier than searching for a free one). If you remove all intervals at some point then the numbers will drop back to 1.

    It might be worth worrying about if it wasn't for the 64 bit numbers used as indexes - that should keep you going some time :)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

clearTimeout not working properly

Posted by Avatar for randunel @randunel

Actions