清除最后创建的计时器对象的超时

时间:2018-07-12 17:50:16

标签: javascript

我是javascript新手,正在玩javascript计时器示例。

我了解到,将计时器的引用存储到某个变量(var o=setTimeout(func;1000))可以使稍后通过调用clearTimeout(o)停止执行变得容易。

但是如果引用未存储在变量中,是否仍然可以在最后一个创建的计时器上调用clearTimeout

以下是我想通过按停止键取消计时器的示例。

<button onclick="setTimeout(helloWorld, 3000)">Start </button>
<button onclick="clearTimeout()">Stop</button>
<script>
function helloWorld() {
    alert("Hello");
    setTimeout(helloWorld, 3000);
}
</script>

2 个答案:

答案 0 :(得分:3)

要详细介绍the answer provided by Hyyan Abo Fakher,请执行以下操作:

class TimerFactory {
  constructor () {
    this.ids = new Set()
  }

  get last () {
    return [...this.ids.values()].pop()
  }

  setTimeout (fn, ms, ...args) {
    const id = setTimeout(() => {
      this.ids.delete(id)
      fn(...args)
    }, ms)

    this.ids.add(id)
    return id
  }

  clearTimeout (id = this.last) {
    this.ids.delete(id)
    return clearTimeout(id)
  }
}

const timer = new TimerFactory()

function helloWorld () {
  console.log('Hello')
  timer.setTimeout(helloWorld, 1000)
}
<button onclick="timer.setTimeout(helloWorld, 1000)">Start </button>
<button onclick="timer.clearTimeout()">Stop</button>

但是,我认为在此处使用setInterval()并带有保护符来防止设置多个时间间隔会更加容易和直观:

let intervalId = null

document.querySelector('[data-action="Start"]').addEventListener('click', () => {
  if (intervalId === null) {
    intervalId = setInterval(() => {
      console.log('Hello')
    }, 1000)
  }
})

document.querySelector('[data-action="Stop"]').addEventListener('click', () => {
  clearTimeout(intervalId)
  intervalId = null
})
[data-action]:before {
  content: attr(data-action);
}
<button data-action="Start"></button>
<button data-action="Stop"></button>

答案 1 :(得分:1)

通常来说,JS中没有允许您在不知道其ID的情况下清除计时器的功能。您需要跟踪它们。

但是您可以将setTimeout包装在另一个跟踪所有创建的计时器的函数中。 (例如,将创建的计时器的ID保存在数组中) 然后在另一个函数中重写clearTimeout,该函数接受要清除的计时器的ID,如果未提供该ID,则清除上一个数组中的最后一个ID

const timers = []
const setTimeout = function(func, time) {
  const id = window.setTimeout(() => {

    const index = timers.indexOf(id);
    if (index > -1) timers.splice(index, 1);

    func()
  }, time);

  timers.push(id);
  return id;
}

const clearTimeout = function(id) {
  if (id) {
    window.clearTimeout(id)
    const index = timers.indexOf(id)
    if (index > -1) timers.splice(index, 1);
  } else if (timers.length > 0) {
    const lastTimer = timers[timers.length - 1]
    window.clearTimeout(lastTimer)
    timers.splice(-1, 1)
  }
}

function helloWorld() {
  console.log("Hello");
  setTimeout(helloWorld, 500);
}
<button onclick="setTimeout(helloWorld, 3000)">Start </button>
<button onclick="clearTimeout()">Stop</button>