skip to Main Content
// generate a random color - random hex value

const randomColor = function () {
  const hex = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += hex[Math.floor(Math.random() * 16)];
  }
  return color;
};

let intervalId;
const startChangingColor = function () {
  intervalId = setInterval(changeBg, 3000);
  function changeBg() {
    document.body.style.backgroundColor = randomColor();
  }
};
const stopChangingColor = function () {
  clearInterval(intervalId);
};

document.querySelector('#start').addEventListener('click', startChangingColor);
document.querySelector('#stop').addEventListener('click', stopChangingColor);

This code has two buttons: one to start and the other to stop. When I click on the start button, the color starts changing. However, when I click on the stop button, it doesn’t work; it should stop the color from changing.

4

Answers


  1. the problem is when you click "start" button, the code doesn’t check if there already has background color change effect. if you click many times "start" button, there will create mulitple background color change effect. While you click "stop", it will ONLY stop last one.

    and in stop interval function, you need reset id to be undefined, it can restart again by click "start" button

    like this:

    // generate a random color - random hex value
    
    const randomColor = function() {
      const hex = '0123456789ABCDEF';
      let color = '#';
      for (let i = 0; i < 6; i++) {
        color += hex[Math.floor(Math.random() * 16)];
      }
      return color;
    };
    
    let intervalId;
    const startChangingColor = function() {
      // need check if already has background change effect
      if (intervalId !== undefined) {
        return;
      }
    
      intervalId = setInterval(changeBg, 3000);
    
      function changeBg() {
        document.body.style.backgroundColor = randomColor();
      }
    
    };
    const stopChangingColor = function() {
      clearInterval(intervalId);
      // reset the id to undefined
      intervalId = undefined;
    };
    
    document.querySelector('#start').addEventListener('click', startChangingColor);
    document.querySelector('#stop').addEventListener('click', stopChangingColor);
    <div>
      <button id="start">start</button>
      <button id="stop">stop</button>
    </div>
    Login or Signup to reply.
  2. Because of how setInterval and clearInterval works, you are better off just calling a stop just before you start to clear out any activate intervals:

    const randomColor = function () {
      const hex = '0123456789ABCDEF';
      let color = '#';
      for (let i = 0; i < 6; i++) {
        color += hex[Math.floor(Math.random() * 16)];
      }
      return color;
    };
    
    let intervalId;
    const startChangingColor = function () {
      stopChangingColor();
      intervalId = setInterval(changeBg, 3000);
      function changeBg() {
        document.body.style.backgroundColor = randomColor();
      }
    };
    const stopChangingColor = function () {
      clearInterval(intervalId);
    };
    
    document.querySelector('#start').addEventListener('click', startChangingColor);
    document.querySelector('#stop').addEventListener('click', stopChangingColor);
    <button id="start">Start</button>
    <button id="stop">Stop</button>

    clearInterval, as you an see in the documentation here, does not care what you pass in:

    If the parameter provided does not identify a previously established action, this method does nothing.

    If it’s a valid interval ID it will cancel it, if it’s anything else it will be ignored, so there’s no need to check if it exists or anything, just clear it with the variable that holds/will hold your ID.

    Login or Signup to reply.
  3. Your provided JavaScript is almost correct. You can see it is working

            const randomColor = function () {
                const hex = '0123456789ABCDEF';
                let color = '#';
                for (let i = 0; i < 6; i++) {
                    color += hex[Math.floor(Math.random() * 16)];
                }
                return color;
            };
    
            let intervalId;
    
            const startChangingColor = function () {
                intervalId = setInterval(changeBg, 3000);
                function changeBg() {
                    document.body.style.backgroundColor = randomColor();
                }
            };
    
            const stopChangingColor = function () {
                clearInterval(intervalId);
            };
    
            document.querySelector('#start').addEventListener('click', startChangingColor);
            document.querySelector('#stop').addEventListener('click', stopChangingColor);
        <button id="start">Start</button>
        <button id="stop">Stop</button>
    Login or Signup to reply.
  4. As described in most of the above answers one of the reason could be that you are creating multiple intervals by consecutively clicking on Start button and then clicking Stop button, which effectively only kills only last created interval.

    My other guess is that, Above snippet that you shared is being used in some library component (eg. React component) which re-renders and losses the value of intervalId on subsequent re-renders. If this is the case then try maintaining intervalId in state.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search