当我多次 运行 相同的函数时,我得到了 setInterval 的多个实例?

I am getting multiple instances of setInterval, when i run same function multiple time?

  
let output = document.getElementById('output');
function startGame(){
  let timerStart = 6;
  let countdown = setInterval(() => {
    timerStart--;
    if(timerStart === 0){
      clearInterval(countdown);
    }
    console.log(timerStart);
    output.innerHTML = timerStart;
    timer.innerHTML = timerStart;
  }, 1000);
}
<button onclick="startGame()">Start Game</button>
          
<p id='output'>output here</p>

问题
当我点击开始游戏时,它工作正常。
输出:5, 4,3,2,1
但是当我多次点击开始游戏时,我也得到了不止一个计时器 运行 像
输出:5, 4, 5,3, 4, 2, 3, 1, 2..etc 请帮助我...

间隔 ID 应该是 persistent(在外部范围内),以便在后续调用 startGame 时,您可以调用 clearInterval在继续代码的其余部分之前:

let output = document.getElementById('output');
let intervalId;
function startGame(){
  // Clear the past interval, if there is one:
  clearInterval(intervalId);

  let timerStart = 6;
  intervalId = setInterval(() => {
    timerStart--;
    if(timerStart === 0){
      clearInterval(intervalId);
    }
    console.log(timerStart);
    output.innerHTML = timerStart;
    timer.innerHTML = timerStart;
  }, 1000);
}

你应该记住之前开始的时间间隔,如果它已经是 运行 就停止它,就像这样

let countdown = null;
let output = document.getElementById('output');
function startGame(){
  let timerStart = 6;
  if (countdown) clearInterval(countdown);
  countdown = setInterval(() => {
    timerStart--;
    if(timerStart === 0){
      clearInterval(countdown);
    }
    console.log(timerStart);
    output.innerHTML = timerStart;
    timer.innerHTML = timerStart;
  }, 1000);
}

因为您没有在任何地方存储倒计时的值,系统需要引用间隔来清除它。在你的函数之外,你应该保留一个包含每个倒计时变量的列表(或其他东西)

真正的问题是当您多次单击该按钮时您希望发生什么。 如果您不想做任何事情,请在游戏开始后第二次单击该按钮。 也许你会做一些像这样的改变。

let output = document.getElementById('output');
let started=false;
function startGame(){
if(started)return;
  let timerStart = 6;
  let countdown = setInterval(() => {
    timerStart--;
    if(timerStart === 0){
      clearInterval(countdown);
started=false;
    }
    console.log(timerStart);
    output.innerHTML = timerStart;
    timer.innerHTML = timerStart;
  }, 1000);
started=true;
}

您需要检查定时器是否已经启动,如果没有则不运行该函数。这可以通过使用保存计时器 ID 的 countdown 变量来完成。如果 id 已填充,则不要再次 运行 函数,除非它达到 0 并被清除:

const startGame = (function(){
    let countdown = null;
    let output = document.getElementById('output');
    function startGame(){
      let timerStart = 6;
      if(countdown){ return; }
      countdown = setInterval(() => {
          timerStart--;
          if(timerStart === 0){
            clearInterval(countdown);
            countdown = null;
          }
          output.innerHTML = timerStart;
      }, 1000);
    }
    return startGame;
})();
<button onclick="startGame()">Start Game</button>
          
<p id='output'>output here</p>

一种可能的解决方案是在 startGame 函数开始时清除间隔:

const output = document.getElementById('output');
let intervalId;    

function displayCounter(counter) {
  output.innerHTML = counter;
  timer.innerHTML = counter;
}

function startGame(){
  clearInterval(intervalId);
  let counter = 5;
  displayCounter(counter);

  intervalId = setInterval(() => {
    if(--counter === 0){
      clearInterval(intervalId);
    }
    console.log(counter);
    displayCounter(counter);
  }, 1000);
}

另一个解决方案是防止用户创建多个间隔

function startGame(){
  if(intervalId) {
    return;
  }

  let counter = 5;
  displayCounter(counter);
  ...