Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
129 views
in Technique[技术] by (71.8m points)

javascript - Prevent addEventListener running another time in forEach loop

First of all I want to know if I am right about cause of the problem.

const updateScore = (isCorrect) => {
  // Update Game Variables
  if (isCorrect === true) {
    counter++;
    score += 100;
  }
};

// Reset Styling
const resetLoadedQuestionStyling = (isCorrect) => {
  questionScreen.style.display = 'none';
  answerArr.forEach(answer => {
    answer.classList.remove('correct');
    answer.classList.remove('wrong');
    answer.classList.remove('disable');
  });
  updateScore(isCorrect);
};

const styleAnswer = (div, isCorrect) => {
  if (isCorrect === true) {
    div.classList.add('correct');
  } else {
    div.classList.add('wrong');
    for (let i = 0; i < answerArr.length; i++) {
      if (i === currentQuestion.correct) {
        answerArr[i].classList.add('correct');
      }
    }
  }

  // Prevent Second Check
  answerArr.forEach(answer => {
    answer.classList.add('disable');
  });

  // Reset Styling
  setTimeout(() => {
    resetLoadedQuestionStyling(isCorrect);
  }, 3000);
};

const checkAnswer = (div, index) => {
  const userChoice = index;
  // Default Answer State
  let isCorrect = false;
  if (userChoice === currentQuestion.correct) {
    isCorrect = true;
  }
  styleAnswer(div, isCorrect);
};

answerArr.forEach((div, index) => {
  div.addEventListener('click', () => {
    checkAnswer(div, index);
  });
});

  1. My counter updates 1,time, that 2 times... and I think the cause of this issue is that my EventListener is in a forEach loop, is that right?

  2. How to prevent it?

Thanks!

EDIT: Addded more of the code in order to get my idea better.

EDIT: answerArr is array of 4 divs in my HTML

question from:https://stackoverflow.com/questions/65928089/prevent-addeventlistener-running-another-time-in-foreach-loop

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There may be a setTimeout-related issue. Every time an answer is clicked, the counter is set to be incremented after 3 seconds.

Here's the sequence when an answer is clicked:

'click'

  checkAnswer ->
    styleAnswer ->
      setTimeout =>
        resetLoadedQuestionStyling ->
          updateScore ->
            counter++

Below is the code with all of the unrelated lines removed. It does increment the counter after every click, but only after 3 seconds.

const answerArr = [...document.querySelectorAll('button')];
let counter = 0;
const span = document.getElementById('counter');

const updateScore = (isCorrect) => {
  if (isCorrect === true) {
    counter++
  }
  span.innerText = counter;
}

const resetLoadedQuestionStyling = (isCorrect) => {
  updateScore(isCorrect)
}

const styleAnswer = (div, isCorrect) => {

  // Reset Styling after 3 seconds
  setTimeout(() => {
    resetLoadedQuestionStyling(isCorrect);
  }, 3000);
}

const checkAnswer = (div, index) => {
  styleAnswer(div, true);
}

answerArr.forEach((div, index) => {
  div.addEventListener('click', () => {
    checkAnswer(div, index);
  });
});
<button>Answer 1</button><br>
<button>Answer 2</button><br>
<button>Answer 3</button><br>
<button>Answer 4</button><br>

<p>Counter: <span id="counter"></span></p>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...