Home > Net >  How to update a variable to use in another scope
How to update a variable to use in another scope

Time:12-02

I have a variable let second = 20 that i make 1 lower until it hits 0. When it hits 0 i want to stop running a part of my code but the variable second is always 20 when i use it because i make it lower in another scope. Sorry if my explenation is a bit unclear.

Here is the code:

votingEnd = document.querySelector(".imposters__voting");
imposters = document.querySelectorAll(".imposter");
let second = 20;

window.addEventListener("load", function () {
  let myinterval;

  myinterval = setInterval(function () {
    second--;

    if (second < 11) {
      votingEnd.style.color = "red";
    }

    votingEnd.innerHTML = `Voting ends in: ${second}s`;
    if (second == 0) {
      clearInterval(myinterval);
      votingEnd.innerHTML = `Voting has ended`;
    }
  }, 1000);
});

if (second > 0) {
  //second is still 20 here because i lowered it in my function above. How can i solve this
  for (let i = 0; i < imposters.length; i  ) {
    imposters[i].addEventListener("click", function () {
      let count = 0;
      while (count < imposters.length) {
        imposters[count  ].classList.remove("voted");
      }
      this.classList.add("voted");
    });
  }
}

CodePudding user response:

You could put the if (second > 0) inside the click function that way it will check for the most recent value of second instead of just once on load like so

for(let i = 0; i < imposters.length; i  ){
    imposters[i].addEventListener("click", function () {
        if (second > 0) {
        let count = 0;
            while (count < imposters.length) {
                imposters[count  ].classList.remove("voted");
                    }
            this.classList.add("voted");
        }
    });

CodePudding user response:

The problem has nothing to do with scope. It has to do with timing. That last part of your code only runs once, before the interval runs twenty times.

Here's the order of operations:

  1. Initialize second to 20.
  2. Bind the countdown function to window.onload. (This does not run yet)
  3. Check if seconds is greater than 0, and it is because the intervals haven't run yet. This is the only time this code ever runs.
  4. window.onload is triggered, and your countdown begins
  5. one second later, seconds is now 19
  6. 19 seconds later seconds is not 0, and the interval is cleared.

So what you need to do is trigger your code in each iteration of the interval.

You want something closer to:

let second = 20;

window.addEventListener("load", function () {
  const myinterval = setInterval(function () {
    second--;

    // other logic here...

    if (second > 0) {
      countdownTick(); // runs every second with the interval handler
    }

    if (second == 0) {
      clearInterval(myinterval);
      // cleanup
    }
  }, 1000);
});

function countdownTick() {
  // Do the stuff you need to do each second here
}

CodePudding user response:

Your setInterval runs every second. That does not mean that the rest of the code also runs every second. Which is why second is still 20 when the code gets to if (second > 0).

So you need to make sure that this part of your code runs every second as well. One solution would be to wrap that code inside a function which you call inside the interval, like this:

votingEnd = document.querySelector(".imposters__voting");
imposters = document.querySelectorAll(".imposter");
let second = 20;

window.addEventListener("load", function () {
  let myinterval;

  myinterval = setInterval(function () {
    second--;

    if (second < 11) {
      votingEnd.style.color = "red";
    }

    votingEnd.innerHTML = `Voting ends in: ${second}s`;
    if (second == 0) {
      clearInterval(myinterval);
      votingEnd.innerHTML = `Voting has ended`;
    }
    check();
  }, 1000);
});

function check() {
if (second > 0) {
  //second is still 20 here because i lowered it in my function above. How can i solve this
  for (let i = 0; i < imposters.length; i  ) {
    imposters[i].addEventListener("click", function () {
      let count = 0;
      while (count < imposters.length) {
        imposters[count  ].classList.remove("voted");
      }
      this.classList.add("voted");
    });
  }
}
}
  • Related