skip to Main Content

I just created a counter class that seems to work almost okay.
Unfortunately there is an issue that I cannot identify.
I instance my class twice with a different name but the parameters remain the same in terms of the chrono max limit.
Thanks to anyone who could help me…

I’m trying to create a class that can display a counter but there is a problem with the parameters. Of course I could just create a simple function instead but that’s not what I’m trying to do. I would like to stay in the same perspective if possible… Thanks to anyone who could help me…

I’ll let you look at the code a little further down.

document.addEventListener("DOMContentLoaded", (event) => {
  console.log("DOM fully loaded and parsed");
});

class SuperCounter {
  constructor(cumul, limit) {
    this.cumul = cumul;
    this.limit = limit;
  }
  add() {
    if (this.cumul === this.limit) {
      console.warn('Counter just reached to the limit');
      clearInterval(ignition)
    };
    return {
      result: this.cumul++,
      //limit: this.limit,
    }
  }
}

const firstCounter = new SuperCounter(1, 50);
const secondCounter = new SuperCounter(1, 150);

const ignition = setInterval(displayCounter, 100);

function displayCounter() {
  document.querySelector("#chrono1").innerHTML = /*html*/ `<h2>Chrono #1 : ${firstCounter.add().result}</h2>`
  document.querySelector("#chrono2").innerHTML = /*html*/ `<h2>Chrono #2 : ${secondCounter.add().result}</h2>`
};
<h3 id="chrono1"></h3>
<h3 id="chrono2"></h3>

2

Answers


  1. The main problem in your code is that you are calling clearInterval() from within your SuperCounter.add() method. What if a SuperCounter object is being used independently of a setInterval()?

    As you want to trigger the add() method of your counters in a synchronized way (in one common setInterval() callback-function) and you want that function to be called repeatedly until both counters have reached their limits you should only call clearInterval(ignition) after both counters are .done. This property is set as soon as the limit of the counter has been reached.

    document.addEventListener("DOMContentLoaded", (event) => {
      console.log("DOM fully loaded and parsed");
    });
    
    class SuperCounter {
      constructor(cumul, limit) {
        this.cumul = cumul-1;
        this.limit = limit;
      }
      add() {
        if (this.cumul == this.limit){
          if(!this.done){
            console.warn('Counter just reached its limit '+this.limit);
            this.done=true;
          }
        } else this.cumul++;
        return this.cumul;
      }
    }
    
    const firstCounter = new SuperCounter(1, 50);
    const secondCounter = new SuperCounter(81, 150);
    
    const ignition = setInterval(displayCounter, 100);
    
    function displayCounter() {
      document.querySelector("#chrono1").innerHTML = /*html*/ `<h2>Chrono #1 : ${firstCounter.add()}</h2>`
      document.querySelector("#chrono2").innerHTML = /*html*/ `<h2>Chrono #2 : ${secondCounter.add()}</h2>`
      if(firstCounter.done&&secondCounter.done) clearInterval(ignition);
    };
    <h3 id="chrono1"></h3>
    <h3 id="chrono2"></h3>

    I also took the liberty of simplifying the return value of your add() method to the current counter value. And, in order to make the demo a little faster, I started the second counter at value 81 ;-).

    Login or Signup to reply.
  2. I wouldn’t use class syntax (why not?). Using setTimeout will give more control to the loop. Here is a demo counter factory function (replacing the class syntax) for some independent counters:

    SuperCounterFactory(document.querySelector(`#cntr1`)).start();
    SuperCounterFactory(document.querySelector(`#cntr2`)).start();
    const cntr3 = SuperCounterFactory(document.querySelector(`#cntr3`));
    cntr3.start();
    
    setTimeout( () => {
      cntr3.reset(); 
      cntr3.start(); }, 21_000);
    
    function SuperCounterFactory(elem) {
      const interval = +elem.dataset.interval ?? 1;
      let [value, limit] = init();
      
      function stop() {
        console.log(`counter for #${elem.id} done`); 
        value = limit; 
      };
      
      function start() {
        value += 1;
        elem.dataset.cnt = value;
        
        if (value < limit) {
          return setTimeout(start, interval * 1000);
        }
        
        return stop();
      }
      
      function init() {
        elem.dataset.from = elem.dataset.from ?? 0;
        elem.dataset.to = elem.dataset.to ?? 100;
        elem.dataset.cnt = elem.dataset.from;
        return [+elem.dataset.cnt, +elem.dataset.to];
      }
      
      function reset() {
        console.log(`reset counter for #${elem.id}`);
        elem.dataset.cnt = 0;
        [value, limit] = init();
      }
      
      return { start, reset };
    }
    [data-cnt]:after {
      content: attr(data-cnt);
    }
    <div id="cntr1" data-from="10" data-to="75" data-interval="0.15"></div>
    <div id="cntr2" data-interval="0.25"></div>
    <div id="cntr3" data-to="50" data-interval="0.4"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search