Why do I need to call clearTimeout twice to reset setTimeout

Tags:



I ran into a puzzle as I was trying to make a rotating banner in JavaScript following this tutorial.

All the images were displayed at fixed intervals with setTimeout. Later I would like to add a button that allows the user to switch to the next image on the banner manually, so I thought I would use clearTimeout to stop the timer for the automatic switching first and then reset it after the manual switch. However, I was confused by the fact that I had to call clearTimeout twice in order to stop the original timer properly before resetting it. Calling clearTimeout once could not stop the timer properly. Can anybody please help explain why is that the case to me? Is there anything wrong with my code? Below is part of the code:

//Global Variables
var switchTimeout;
myBanner = new Array("img/chicken.jpg", "img/tiger.jpg", "img/pig.jpg");
var bannerCounter = 0;

//Called after the page is loaded
function switchBanner() {
  if (document.images) {
    bannerCounter++;
    if (bannerCounter == myBanner.length) {
      bannerCounter = 0;
    }
    document.getElementById("banner").src = myBanner[bannerCounter];
    switchTimeout = setTimeout("switchBanner()",3000);
  }
}

//Called when user hits the button
function manualSwitch() {
  //Why do I need to call this twice for it to work?
  clearTimeout(switchTimeout);
  clearTimeout(switchTimeout);
  if (document.images) {
    bannerCounter++;
    console.log(bannerCounter);
    if (bannerCounter == myBanner.length) {
      bannerCounter = 0;
    }
    document.getElementById("banner").src = myBanner[bannerCounter];
    //Reset the timer now
    switchTimeout = setTimeout("switchBanner()",3000); 
  }
}

Many thanks for your help!

Answer

I tested this and seems to work fine with calling only once, that said, this seems to be better suited to use setInterval() instead of setTimeout(). Also reducing some unnecessary code repetition.

See example using just text instead of replacing an img‘s source.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="banner"> </div>
    <button onclick="changeAndTriggerInterval()" id="bannerSwitcher">Switch Banner</button>
    <script>
        let intervalIdentifier = 0;
        let  bannerCounter = 0;
        myBanner = new Array("img/chicken.jpg", "img/tiger.jpg", "img/pig.jpg");
        // Called when user hits the button and on initial page load
        function changeAndTriggerInterval() {
            changeBanner();
            resetBannerChanger();
        }

        function resetBannerChanger() {
            if (intervalIdentifier > 0) {
                clearInterval(intervalIdentifier);
            }
            intervalIdentifier = setInterval(changeBanner, 3000);
        }

        function changeBanner() {
            // Change before updating counter to start from index 0
            document.getElementById("banner").innerText = myBanner[bannerCounter];
            bannerCounter++;
            if (bannerCounter == myBanner.length) {
                bannerCounter = 0;
            }
        }
        window.onload = changeAndTriggerInterval;
    </script>

</body>

</html>


Source: stackoverflow