代码之家  ›  专栏  ›  技术社区  ›  nyi

清除上次创建的计时器对象的超时

  •  0
  • nyi  · 技术社区  · 7 年前

    我对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 回复  |  直到 7 年前
        1
  •  3
  •   Patrick Roberts Benjamin Gruenbaum    7 年前

    详述 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>
        2
  •  1
  •   Hyyan Abo Fakher JM1    7 年前

    一般来说,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>