javascript: 暂停 setTimeout();

发布于 2024-09-28 07:22:48 字数 196 浏览 5 评论 0原文

如果我有一个通过设置的活动超时正在运行,

var t = setTimeout("dosomething()", 5000)

是否有办法暂停和恢复它?

有什么办法可以获取当前超时的剩余时间吗?

或者我必须在一个变量中,当设置超时时,存储当前时间,然后我们暂停,得到现在和那时之间的差异?

If I have an active timeout running that was set through

var t = setTimeout("dosomething()", 5000)

Is there anyway to pause and resume it?

Is there any way to get the time remaining on the current timeout?

or do I have to in a variable, when the timeout is set, store the current time, then we we pause, get the difference between now and then?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

落墨 2024-10-05 07:22:48

您可以像这样包装 window.setTimeout ,我认为这与您在问题中建议的类似:

var Timer = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        timerId = null;
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        if (timerId) {
            return;
        }

        start = Date.now();
        timerId = window.setTimeout(callback, remaining);
    };

    this.resume();
};

var timer = new Timer(function() {
    alert("Done!");
}, 1000);

timer.pause();
// Do some stuff...
timer.resume();

You could wrap window.setTimeout like this, which I think is similar to what you were suggesting in the question:

var Timer = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        timerId = null;
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        if (timerId) {
            return;
        }

        start = Date.now();
        timerId = window.setTimeout(callback, remaining);
    };

    this.resume();
};

var timer = new Timer(function() {
    alert("Done!");
}, 1000);

timer.pause();
// Do some stuff...
timer.resume();
二手情话 2024-10-05 07:22:48

像这样的事情应该可以解决问题。

function Timer(fn, countdown) {
    var ident, complete = false;

    function _time_diff(date1, date2) {
        return date2 ? date2 - date1 : new Date().getTime() - date1;
    }

    function cancel() {
        clearTimeout(ident);
    }

    function pause() {
        clearTimeout(ident);
        total_time_run = _time_diff(start_time);
        complete = total_time_run >= countdown;
    }

    function resume() {
        ident = complete ? -1 : setTimeout(fn, countdown - total_time_run);
    }

    var start_time = new Date().getTime();
    ident = setTimeout(fn, countdown);

    return { cancel: cancel, pause: pause, resume: resume };
}

Something like this should do the trick.

function Timer(fn, countdown) {
    var ident, complete = false;

    function _time_diff(date1, date2) {
        return date2 ? date2 - date1 : new Date().getTime() - date1;
    }

    function cancel() {
        clearTimeout(ident);
    }

    function pause() {
        clearTimeout(ident);
        total_time_run = _time_diff(start_time);
        complete = total_time_run >= countdown;
    }

    function resume() {
        ident = complete ? -1 : setTimeout(fn, countdown - total_time_run);
    }

    var start_time = new Date().getTime();
    ident = setTimeout(fn, countdown);

    return { cancel: cancel, pause: pause, resume: resume };
}
棒棒糖 2024-10-05 07:22:48

Tim Downs 答案的稍微修改版本。但是,由于蒂姆回滚我的编辑,我必须回答这个我自己。我的解决方案可以使用额外的参数作为第三个参数(3、4、5...)并清除计时器:

function Timer(callback, delay) {
    var args = arguments,
        self = this,
        timer, start;

    this.clear = function () {
        clearTimeout(timer);
    };

    this.pause = function () {
        this.clear();
        delay -= new Date() - start;
    };

    this.resume = function () {
        start = new Date();
        timer = setTimeout(function () {
            callback.apply(self, Array.prototype.slice.call(args, 2, args.length));
        }, delay);
    };

    this.resume();
}

正如 Tim 提到的,额外的参数在 IE lt 中不可用9,但是我做了一些工作,以便它也可以在 oldIE 中工作。

用法:new Timer(Function, Number, arg1, arg2, arg3...)

function callback(foo, bar) {
    console.log(foo); // "foo"
    console.log(bar); // "bar"
}

var timer = new Timer(callback, 1000, "foo", "bar");

timer.pause();
document.onclick = timer.resume;

A slightly modified version of Tim Downs answer. However, since Tim rolled back my edit, I've to answer this myself. My solution makes it possible to use extra arguments as third (3, 4, 5...) parameter and to clear the timer:

function Timer(callback, delay) {
    var args = arguments,
        self = this,
        timer, start;

    this.clear = function () {
        clearTimeout(timer);
    };

    this.pause = function () {
        this.clear();
        delay -= new Date() - start;
    };

    this.resume = function () {
        start = new Date();
        timer = setTimeout(function () {
            callback.apply(self, Array.prototype.slice.call(args, 2, args.length));
        }, delay);
    };

    this.resume();
}

As Tim mentioned, extra parameters are not available in IE lt 9, however I worked a bit around so that it will work in oldIE's too.

Usage: new Timer(Function, Number, arg1, arg2, arg3...)

function callback(foo, bar) {
    console.log(foo); // "foo"
    console.log(bar); // "bar"
}

var timer = new Timer(callback, 1000, "foo", "bar");

timer.pause();
document.onclick = timer.resume;
月下伊人醉 2024-10-05 07:22:48

不可以。您需要取消它 (clearTimeout),测量自启动以来的时间并使用新时间重新启动它。

No. You'll need cancel it (clearTimeout), measure the time since you started it and restart it with the new time.

隐诗 2024-10-05 07:22:48

超时很容易找到解决方案,但间隔有点棘手。

我想出了以下两个类来解决这个问题:

function PauseableTimeout(func, delay){
    this.func = func;

    var _now = new Date().getTime();
    this.triggerTime = _now + delay;

    this.t = window.setTimeout(this.func,delay);

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();

        return this.triggerTime - now;
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();

        window.clearTimeout(this.t);
        this.t = null;
    }

    this.resume = function(){
        if (this.t == null){
            this.t = window.setTimeout(this.func, this.paused_timeLeft);
        }
    }

    this.clearTimeout = function(){ window.clearTimeout(this.t);}
}

function PauseableInterval(func, delay){
    this.func = func;
    this.delay = delay;

    this.triggerSetAt = new Date().getTime();
    this.triggerTime = this.triggerSetAt + this.delay;

    this.i = window.setInterval(this.func, this.delay);

    this.t_restart = null;

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();
        return this.delay - ((now - this.triggerSetAt) % this.delay);
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();
        window.clearInterval(this.i);
        this.i = null;
    }

    this.restart = function(sender){
        sender.i = window.setInterval(sender.func, sender.delay);
    }

    this.resume = function(){
        if (this.i == null){
            this.i = window.setTimeout(this.restart, this.paused_timeLeft, this);
        }
    }

    this.clearInterval = function(){ window.clearInterval(this.i);}
}

这些可以这样实现:

var pt_hey = new PauseableTimeout(function(){
    alert("hello");
}, 2000);

window.setTimeout(function(){
    pt_hey.pause();
}, 1000);

window.setTimeout("pt_hey.start()", 2000);

这个示例将设置一个可暂停的超时(pt_hey),计划在两秒后发出“嘿”警报。另一次超时在一秒后暂停 pt_hey。两秒后第三次超时恢复 pt_hey。 pt_hey 运行一秒,暂停一秒,然后恢复运行。 pt_hey 在三秒后触发。

现在是更棘手的间隔

var pi_hey = new PauseableInterval(function(){
    console.log("hello world");
}, 2000);

window.setTimeout("pi_hey.pause()", 5000);

window.setTimeout("pi_hey.resume()", 6000);

此示例设置一个可暂停的间隔 (pi_hey),每两秒在控制台中写入“hello world”。超时会在五秒后暂停 pi_hey。六秒后,另一个超时恢复 pi_hey。所以pi_hey会触发两次,运行一秒,暂停一秒,运行一秒,然后每2秒继续触发一次。

其他函数

  • clearTimeout()clearInterval()

    pt_hey.clearTimeout();pi_hey.clearInterval(); 是清除超时和间隔的简单方法。

  • getTimeLeft()

    pt_hey.getTimeLeft();pi_hey.getTimeLeft(); 将返回距离下一次触发计划发生还有多少毫秒。

The Timeout was easy enough to find a solution for, but the Interval was a little bit trickier.

I came up with the following two classes to solve this issues:

function PauseableTimeout(func, delay){
    this.func = func;

    var _now = new Date().getTime();
    this.triggerTime = _now + delay;

    this.t = window.setTimeout(this.func,delay);

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();

        return this.triggerTime - now;
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();

        window.clearTimeout(this.t);
        this.t = null;
    }

    this.resume = function(){
        if (this.t == null){
            this.t = window.setTimeout(this.func, this.paused_timeLeft);
        }
    }

    this.clearTimeout = function(){ window.clearTimeout(this.t);}
}

function PauseableInterval(func, delay){
    this.func = func;
    this.delay = delay;

    this.triggerSetAt = new Date().getTime();
    this.triggerTime = this.triggerSetAt + this.delay;

    this.i = window.setInterval(this.func, this.delay);

    this.t_restart = null;

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();
        return this.delay - ((now - this.triggerSetAt) % this.delay);
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();
        window.clearInterval(this.i);
        this.i = null;
    }

    this.restart = function(sender){
        sender.i = window.setInterval(sender.func, sender.delay);
    }

    this.resume = function(){
        if (this.i == null){
            this.i = window.setTimeout(this.restart, this.paused_timeLeft, this);
        }
    }

    this.clearInterval = function(){ window.clearInterval(this.i);}
}

These can be implemented as such:

var pt_hey = new PauseableTimeout(function(){
    alert("hello");
}, 2000);

window.setTimeout(function(){
    pt_hey.pause();
}, 1000);

window.setTimeout("pt_hey.start()", 2000);

This example will set a pauseable Timeout (pt_hey) which is scheduled to alert, "hey" after two seconds. Another Timeout pauses pt_hey after one second. A third Timeout resumes pt_hey after two seconds. pt_hey runs for one second, pauses for one second, then resumes running. pt_hey triggers after three seconds.

Now for the trickier intervals

var pi_hey = new PauseableInterval(function(){
    console.log("hello world");
}, 2000);

window.setTimeout("pi_hey.pause()", 5000);

window.setTimeout("pi_hey.resume()", 6000);

This example sets a pauseable Interval (pi_hey) to write "hello world" in the console every two seconds. A timeout pauses pi_hey after five seconds. Another timeout resumes pi_hey after six seconds. So pi_hey will trigger twice, run for one second, pause for one second, run for one second, and then continue triggering every 2 seconds.

OTHER FUNCTIONS

  • clearTimeout() and clearInterval()

    pt_hey.clearTimeout(); and pi_hey.clearInterval(); serve as an easy way to clear the timeouts and intervals.

  • getTimeLeft()

    pt_hey.getTimeLeft(); and pi_hey.getTimeLeft(); will return how many milliseconds till the next trigger is scheduled to occur.

Spring初心 2024-10-05 07:22:48

“暂停”和“恢复”在 setTimeout 的上下文中并没有多大意义,这是一次性的事情。您可能想要暂停一系列setTimeout调用的链式,在这种情况下,只需不要安排下一个调用(也许可以通过clearTimeout<取消未完成的调用) /code>,如下)。但 setTimeout 本身并不循环,没有什么可以暂停和恢复的。

如果您的意思是setInterval,那么不,您无法暂停它,只能取消它(clearInterval),然后再次重新安排。所有这些的详细信息请参见规范的计时器部分

// Setting
var t = setInterval(doSomething, 1000);

// Pausing (which is really stopping)
clearInterval(t);
t = 0;

// Resuming (which is really just setting again)
t = setInterval(doSomething, 1000);

"Pause" and "resume" don't really make much sense in the context of setTimeout, which is a one-off thing. You might want to pause a chained series of setTimeout calls, in which case just don't schedule the next one (perhaps cancel the one that's outstanding via clearTimeout, as below). But setTimeout itself doesn't loop, there's nothing to pause and resume.

If you mean setInterval then no, you can't pause it, you can only cancel it (clearInterval) and then re-schedule it again. Details of all of these in the Timers section of the spec.

// Setting
var t = setInterval(doSomething, 1000);

// Pausing (which is really stopping)
clearInterval(t);
t = 0;

// Resuming (which is really just setting again)
t = setInterval(doSomething, 1000);
套路撩心 2024-10-05 07:22:48

/revive

使用 Class-y 语法糖的 ES6 版本

/revive

ES6 Version using Class-y syntactic sugar ????

(slightly-modified: added start())

class Timer {
  constructor(callback, delay) {
    this.callback = callback
    this.remainingTime = delay
    this.startTime
    this.timerId
  }

  pause() {
    clearTimeout(this.timerId)
    this.remainingTime -= new Date() - this.startTime
  }

  resume() {
    this.startTime = new Date()
    clearTimeout(this.timerId)
    this.timerId = setTimeout(this.callback, this.remainingTime)
  }

  start() {
    this.timerId = setTimeout(this.callback, this.remainingTime)
  }
}

// supporting code
const pauseButton = document.getElementById('timer-pause')
const resumeButton = document.getElementById('timer-resume')
const startButton = document.getElementById('timer-start')

const timer = new Timer(() => {
  console.log('called');
  document.getElementById('change-me').classList.add('wow')
}, 3000)

pauseButton.addEventListener('click', timer.pause.bind(timer))
resumeButton.addEventListener('click', timer.resume.bind(timer))
startButton.addEventListener('click', timer.start.bind(timer))
<!doctype html>
<html>
<head>
  <title>Traditional HTML Document. ZZz...</title>
  <style type="text/css">
    .wow { color: blue; font-family: Tahoma, sans-serif; font-size: 1em; }
  </style>
</head>
<body>
  <h1>DOM & JavaScript</h1>

  <div id="change-me">I'm going to repaint my life, wait and see.</div>

  <button id="timer-start">Start!</button>
  <button id="timer-pause">Pause!</button>
  <button id="timer-resume">Resume!</button>
</body>
</html>

花落人断肠 2024-10-05 07:22:48

基于最高评价答案的打字稿实现

/** Represents the `setTimeout` with an ability to perform pause/resume actions */
export class Timer {
    private _start: Date;
    private _remaining: number;
    private _durationTimeoutId?: NodeJS.Timeout;
    private _callback: (...args: any[]) => void;
    private _done = false;
    get done () {
        return this._done;
    }

    constructor(callback: (...args: any[]) => void, ms = 0) {
        this._callback = () => {
            callback();
            this._done = true;
        };
        this._remaining = ms;
        this.resume();
    }

    /** pauses the timer */
    pause(): Timer {
        if (this._durationTimeoutId && !this._done) {
            this._clearTimeoutRef();
            this._remaining -= new Date().getTime() - this._start.getTime();
        }
        return this;
    }

    /** resumes the timer */
    resume(): Timer {
        if (!this._durationTimeoutId && !this._done) {
            this._start = new Date;
            this._durationTimeoutId = setTimeout(this._callback, this._remaining);
        }
        return this;
    }

    /** 
     * clears the timeout and marks it as done. 
     * 
     * After called, the timeout will not resume
     */
    clearTimeout() {
        this._clearTimeoutRef();
        this._done = true;
    }

    private _clearTimeoutRef() {
        if (this._durationTimeoutId) {
            clearTimeout(this._durationTimeoutId);
            this._durationTimeoutId = undefined;
        }
    }

}

Typescript implementation based on top rated answer

/** Represents the `setTimeout` with an ability to perform pause/resume actions */
export class Timer {
    private _start: Date;
    private _remaining: number;
    private _durationTimeoutId?: NodeJS.Timeout;
    private _callback: (...args: any[]) => void;
    private _done = false;
    get done () {
        return this._done;
    }

    constructor(callback: (...args: any[]) => void, ms = 0) {
        this._callback = () => {
            callback();
            this._done = true;
        };
        this._remaining = ms;
        this.resume();
    }

    /** pauses the timer */
    pause(): Timer {
        if (this._durationTimeoutId && !this._done) {
            this._clearTimeoutRef();
            this._remaining -= new Date().getTime() - this._start.getTime();
        }
        return this;
    }

    /** resumes the timer */
    resume(): Timer {
        if (!this._durationTimeoutId && !this._done) {
            this._start = new Date;
            this._durationTimeoutId = setTimeout(this._callback, this._remaining);
        }
        return this;
    }

    /** 
     * clears the timeout and marks it as done. 
     * 
     * After called, the timeout will not resume
     */
    clearTimeout() {
        this._clearTimeoutRef();
        this._done = true;
    }

    private _clearTimeoutRef() {
        if (this._durationTimeoutId) {
            clearTimeout(this._durationTimeoutId);
            this._durationTimeoutId = undefined;
        }
    }

}
哭泣的笑容 2024-10-05 07:22:48

我需要计算已用时间和剩余时间以显示进度条。使用已接受的答案并不容易。对于此任务,“setInterval”比“setTimeout”更好。因此,我创建了这个可以在任何项目中使用的 Timer 类。

https://jsfiddle.net/ashraffayad/t0mmv853/

'use strict';


    //Constructor
    var Timer = function(cb, delay) {
      this.cb = cb;
      this.delay = delay;
      this.elapsed = 0;
      this.remaining = this.delay - self.elapsed;
    };

    console.log(Timer);

    Timer.prototype = function() {
      var _start = function(x, y) {
          var self = this;
          if (self.elapsed < self.delay) {
            clearInterval(self.interval);
            self.interval = setInterval(function() {
              self.elapsed += 50;
              self.remaining = self.delay - self.elapsed;
              console.log('elapsed: ' + self.elapsed, 
                          'remaining: ' + self.remaining, 
                          'delay: ' + self.delay);
              if (self.elapsed >= self.delay) {
                clearInterval(self.interval);
                self.cb();
              }
            }, 50);
          }
        },
        _pause = function() {
          var self = this;
          clearInterval(self.interval);
        },
        _restart = function() {
          var self = this;
          self.elapsed = 0;
          console.log(self);
          clearInterval(self.interval);
          self.start();
        };

      //public member definitions
      return {
        start: _start,
        pause: _pause,
        restart: _restart
      };
    }();


    // - - - - - - - - how to use this class

    var restartBtn = document.getElementById('restart');
    var pauseBtn = document.getElementById('pause');
    var startBtn = document.getElementById('start');

    var timer = new Timer(function() {
      console.log('Done!');
    }, 2000);

    restartBtn.addEventListener('click', function(e) {
      timer.restart();
    });
    pauseBtn.addEventListener('click', function(e) {
      timer.pause();
    });
    startBtn.addEventListener('click', function(e) {
      timer.start();
    });

I needed to calculate the elapsed and remaining time to show a progress-bar. It was not easy using the accepted answer. 'setInterval' is better than 'setTimeout' for this task. So, I created this Timer class that you can use in any project.

https://jsfiddle.net/ashraffayad/t0mmv853/

'use strict';


    //Constructor
    var Timer = function(cb, delay) {
      this.cb = cb;
      this.delay = delay;
      this.elapsed = 0;
      this.remaining = this.delay - self.elapsed;
    };

    console.log(Timer);

    Timer.prototype = function() {
      var _start = function(x, y) {
          var self = this;
          if (self.elapsed < self.delay) {
            clearInterval(self.interval);
            self.interval = setInterval(function() {
              self.elapsed += 50;
              self.remaining = self.delay - self.elapsed;
              console.log('elapsed: ' + self.elapsed, 
                          'remaining: ' + self.remaining, 
                          'delay: ' + self.delay);
              if (self.elapsed >= self.delay) {
                clearInterval(self.interval);
                self.cb();
              }
            }, 50);
          }
        },
        _pause = function() {
          var self = this;
          clearInterval(self.interval);
        },
        _restart = function() {
          var self = this;
          self.elapsed = 0;
          console.log(self);
          clearInterval(self.interval);
          self.start();
        };

      //public member definitions
      return {
        start: _start,
        pause: _pause,
        restart: _restart
      };
    }();


    // - - - - - - - - how to use this class

    var restartBtn = document.getElementById('restart');
    var pauseBtn = document.getElementById('pause');
    var startBtn = document.getElementById('start');

    var timer = new Timer(function() {
      console.log('Done!');
    }, 2000);

    restartBtn.addEventListener('click', function(e) {
      timer.restart();
    });
    pauseBtn.addEventListener('click', function(e) {
      timer.pause();
    });
    startBtn.addEventListener('click', function(e) {
      timer.start();
    });
画尸师 2024-10-05 07:22:48
class pausable_timeout {
  constructor(func, milliseconds) {
    this.func = func;
    this.date_ms = new Date().valueOf();
    this.timeout = setTimeout(func, milliseconds);
    this.time_left = milliseconds;
  };

  pause() {
    clearTimeout(this.timeout);
    const elapsed_time = new Date().valueOf() - this.date_ms;
    this.time_left -= elapsed_time;
  };

  unpause() {
    this.timeout = setTimeout(this.func, this.time_left);
    this.date_ms = new Date().valueOf();
  };
};

const timer = new pausable_timeout(() => /* your code */, 3000 /* your timeout in milliseconds */);
timer.pause();
timer.unpause();

该程序相当简单。我们将创建一个包含两个函数的类:pause 函数和unpause 函数。

pause 函数将清除 setTimeout 并将开始到现在之间经过的时间存储在 time_left 变量中。 unpause 函数将通过将 time_left 时间作为参数来重新创建 setTimeout

class pausable_timeout {
  constructor(func, milliseconds) {
    this.func = func;
    this.date_ms = new Date().valueOf();
    this.timeout = setTimeout(func, milliseconds);
    this.time_left = milliseconds;
  };

  pause() {
    clearTimeout(this.timeout);
    const elapsed_time = new Date().valueOf() - this.date_ms;
    this.time_left -= elapsed_time;
  };

  unpause() {
    this.timeout = setTimeout(this.func, this.time_left);
    this.date_ms = new Date().valueOf();
  };
};

const timer = new pausable_timeout(() => /* your code */, 3000 /* your timeout in milliseconds */);
timer.pause();
timer.unpause();

The programme is rather simple. We will create a class containing two functions, the pause function and the unpause function.

The pause function will clear the setTimeout and store the time that has elapsed between the start and now in the time_left variable. The unpause function will recreate a setTimeout by putting the time_left time as an argument.

阪姬 2024-10-05 07:22:48

您可以查看 clearTimeout()

或根据设置的全局变量暂停达到一定条件。就像按下按钮一样。

  <button onclick="myBool = true" > pauseTimeout </button>

  <script>
  var myBool = false;

  var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000);
  </script>

You could look into clearTimeout()

or pause depending on a global variable that is set when a certain condition is hit. Like a button is pressed.

  <button onclick="myBool = true" > pauseTimeout </button>

  <script>
  var myBool = false;

  var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000);
  </script>
月下凄凉 2024-10-05 07:22:48

您还可以通过事件来实现它。

您无需计算时间差,而是开始和停止监听在后台持续运行的“tick”事件:

var Slideshow = {

  _create: function(){                  
    this.timer = window.setInterval(function(){
      $(window).trigger('timer:tick'); }, 8000);
  },

  play: function(){            
    $(window).bind('timer:tick', function(){
      // stuff
    });       
  },

  pause: function(){        
    $(window).unbind('timer:tick');
  }

};

You could also implement it with events.

Instead of calculating the time difference, you start and stop listening to a 'tick' event which keeps running in the background:

var Slideshow = {

  _create: function(){                  
    this.timer = window.setInterval(function(){
      $(window).trigger('timer:tick'); }, 8000);
  },

  play: function(){            
    $(window).bind('timer:tick', function(){
      // stuff
    });       
  },

  pause: function(){        
    $(window).unbind('timer:tick');
  }

};
人生戏 2024-10-05 07:22:48

如果您无论如何都使用 jquery,请查看 $.doTimeout 插件。这个东西比 setTimeout 是一个巨大的改进,包括让你用你指定的单个字符串 id 来跟踪你的超时,并且每次设置它时都不会改变,并实现简单的取消、轮询循环和超时。去抖动等等。我最常用的 jquery 插件之一。

不幸的是,它不支持开箱即用的暂停/恢复。为此,您需要包装或扩展 $.doTimeout,大概与接受的答案类似。

If you're using jquery anyhow, check out the $.doTimeout plugin. This thing is a huge improvement over setTimeout, including letting you keep track of your time-outs with a single string id that you specify and that doesn't change every time you set it, and implement easy canceling, polling loops & debouncing, and more. One of my most-used jquery plugins.

Unfortunately, it doesn't support pause/resume out of the box. For this, you would need to wrap or extend $.doTimeout, presumably similarly to the accepted answer.

梅倚清风 2024-10-05 07:22:48

我需要能够暂停 setTimeout() 以实现类似幻灯片的功能。

这是我自己实现的可暂停计时器。它集成了在 Tim Down 的答案中看到的评论,例如更好的暂停(内核的评论)和原型设计的形式(Umur Gedik 的评论)。

function Timer( callback, delay ) {

    /** Get access to this object by value **/
    var self = this;



    /********************* PROPERTIES *********************/
    this.delay = delay;
    this.callback = callback;
    this.starttime;// = ;
    this.timerID = null;


    /********************* METHODS *********************/

    /**
     * Pause
     */
    this.pause = function() {
        /** If the timer has already been paused, return **/
        if ( self.timerID == null ) {
            console.log( 'Timer has been paused already.' );
            return;
        }

        /** Pause the timer **/
        window.clearTimeout( self.timerID );
        self.timerID = null;    // this is how we keep track of the timer having beem cleared

        /** Calculate the new delay for when we'll resume **/
        self.delay = self.starttime + self.delay - new Date().getTime();
        console.log( 'Paused the timer. Time left:', self.delay );
    }


    /**
     * Resume
     */
    this.resume = function() {
        self.starttime = new Date().getTime();
        self.timerID = window.setTimeout( self.callback, self.delay );
        console.log( 'Resuming the timer. Time left:', self.delay );
    }


    /********************* CONSTRUCTOR METHOD *********************/

    /**
     * Private constructor
     * Not a language construct.
     * Mind var to keep the function private and () to execute it right away.
     */
    var __construct = function() {
        self.starttime = new Date().getTime();
        self.timerID = window.setTimeout( self.callback, self.delay )
    }();    /* END __construct */

}   /* END Timer */

示例:

var timer = new Timer( function(){ console.log( 'hey! this is a timer!' ); }, 10000 );
timer.pause();

要测试代码,请使用 timer.resume()timer.pause() 几次并检查还剩多少时间。 (确保您的控制台已打开。)

使用此对象代替 setTimeout() 就像将 timerID = setTimeout( mycallback, 1000) 替换为 timer = new Timer( mycallback, 1000) 一样简单)。然后您可以使用 timer.pause()timer.resume()

I needed to be able to pause setTimeout() for slideshow-like feature.

Here is my own implementation of a pausable timer. It integrates comments seen on Tim Down's answer, such as better pause (kernel's comment) and a form of prototyping (Umur Gedik's comment.)

function Timer( callback, delay ) {

    /** Get access to this object by value **/
    var self = this;



    /********************* PROPERTIES *********************/
    this.delay = delay;
    this.callback = callback;
    this.starttime;// = ;
    this.timerID = null;


    /********************* METHODS *********************/

    /**
     * Pause
     */
    this.pause = function() {
        /** If the timer has already been paused, return **/
        if ( self.timerID == null ) {
            console.log( 'Timer has been paused already.' );
            return;
        }

        /** Pause the timer **/
        window.clearTimeout( self.timerID );
        self.timerID = null;    // this is how we keep track of the timer having beem cleared

        /** Calculate the new delay for when we'll resume **/
        self.delay = self.starttime + self.delay - new Date().getTime();
        console.log( 'Paused the timer. Time left:', self.delay );
    }


    /**
     * Resume
     */
    this.resume = function() {
        self.starttime = new Date().getTime();
        self.timerID = window.setTimeout( self.callback, self.delay );
        console.log( 'Resuming the timer. Time left:', self.delay );
    }


    /********************* CONSTRUCTOR METHOD *********************/

    /**
     * Private constructor
     * Not a language construct.
     * Mind var to keep the function private and () to execute it right away.
     */
    var __construct = function() {
        self.starttime = new Date().getTime();
        self.timerID = window.setTimeout( self.callback, self.delay )
    }();    /* END __construct */

}   /* END Timer */

Example:

var timer = new Timer( function(){ console.log( 'hey! this is a timer!' ); }, 10000 );
timer.pause();

To test the code out, use timer.resume() and timer.pause() a few times and check how much time is left. (Make sure your console is open.)

Using this object in place of setTimeout() is as easy as replacing timerID = setTimeout( mycallback, 1000) with timer = new Timer( mycallback, 1000 ). Then timer.pause() and timer.resume() are available to you.

心作怪 2024-10-05 07:22:48
function delay (ms)   {  return new Promise(resolve => setTimeout(resolve, s));  }

“异步”工作演示位于:
网站 zarsoft.info

function delay (ms)   {  return new Promise(resolve => setTimeout(resolve, s));  }

"async" working demo at:
site zarsoft.info

夕嗳→ 2024-10-05 07:22:48

您可以像下面一样使 setTimeout 在服务器端(Node.js)可暂停

const PauseableTimeout = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        global.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        global.clearTimeout(timerId);
        timerId = global.setTimeout(callback, remaining);
    };

    this.resume();
};

,并且您可以按如下方式检查它

var timer = new PauseableTimeout(function() {
    console.log("Done!");
}, 3000);
setTimeout(()=>{
    timer.pause();
    console.log("setTimeout paused");
},1000);

setTimeout(()=>{
    console.log("setTimeout time complete");
},3000)

setTimeout(()=>{
    timer.resume();
    console.log("setTimeout resume again");
},5000)

You can do like below to make setTimeout pausable on server side (Node.js)

const PauseableTimeout = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        global.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        global.clearTimeout(timerId);
        timerId = global.setTimeout(callback, remaining);
    };

    this.resume();
};

and you can check it as below

var timer = new PauseableTimeout(function() {
    console.log("Done!");
}, 3000);
setTimeout(()=>{
    timer.pause();
    console.log("setTimeout paused");
},1000);

setTimeout(()=>{
    console.log("setTimeout time complete");
},3000)

setTimeout(()=>{
    timer.resume();
    console.log("setTimeout resume again");
},5000)
夜光 2024-10-05 07:22:48

如果有人想要@SeanVieira 阁下在此处分享的 TypeScript 版本,您可以使用以下命令:

    public timer(fn: (...args: any[]) => void, countdown: number): { onCancel: () => void, onPause: () => void, onResume: () => void } {
        let ident: NodeJS.Timeout | number;
        let complete = false;
        let totalTimeRun: number;
        const onTimeDiff = (date1: number, date2: number) => {
            return date2 ? date2 - date1 : new Date().getTime() - date1;
        };

        const handlers = {
            onCancel: () => {
                clearTimeout(ident as NodeJS.Timeout);
            },
            onPause: () => {
                clearTimeout(ident as NodeJS.Timeout);
                totalTimeRun = onTimeDiff(startTime, null);
                complete = totalTimeRun >= countdown;
            },
            onResume: () => {
                ident = complete ? -1 : setTimeout(fn, countdown - totalTimeRun);
            }
        };

        const startTime = new Date().getTime();
        ident = setTimeout(fn, countdown);

        return handlers;
    }

If anyone wants the TypeScript version shared by the Honorable @SeanVieira here, you can use this:

    public timer(fn: (...args: any[]) => void, countdown: number): { onCancel: () => void, onPause: () => void, onResume: () => void } {
        let ident: NodeJS.Timeout | number;
        let complete = false;
        let totalTimeRun: number;
        const onTimeDiff = (date1: number, date2: number) => {
            return date2 ? date2 - date1 : new Date().getTime() - date1;
        };

        const handlers = {
            onCancel: () => {
                clearTimeout(ident as NodeJS.Timeout);
            },
            onPause: () => {
                clearTimeout(ident as NodeJS.Timeout);
                totalTimeRun = onTimeDiff(startTime, null);
                complete = totalTimeRun >= countdown;
            },
            onResume: () => {
                ident = complete ? -1 : setTimeout(fn, countdown - totalTimeRun);
            }
        };

        const startTime = new Date().getTime();
        ident = setTimeout(fn, countdown);

        return handlers;
    }
じ违心 2024-10-05 07:22:48

我在 TypeScript 中为滑块功能创建了以下代码:

class TimeoutSlider {
  private callback: () => void;
  private duration: number;
  private timeReaming: number;
  private startTime: number | null = null;
  private timerId: NodeJS.Timeout | null = null;

  constructor(callback: () => void, duration: number) {
    this.callback = callback;
    this.duration = duration;
    this.timeReaming = duration;
  }

  public start() {
    this.clear();
    this.startTime = new Date().getTime();
    this.timerId = setTimeout(this.callback, this.duration);
  }

  public pause() {
    if (!this.startTime) {
      throw new Error("Cannot pause a timer that has not been started");
    }
    this.clear();
    this.timeReaming = this.duration - (new Date().getTime() - this.startTime);
  }

  public resume() {
    this.clear();
    this.startTime = new Date().getTime();
    this.timerId = setTimeout(this.callback, this.timeReaming);
  }

  private clear() {
    if (this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }
  }
}

I created this code in TypeScript for slider feature:

class TimeoutSlider {
  private callback: () => void;
  private duration: number;
  private timeReaming: number;
  private startTime: number | null = null;
  private timerId: NodeJS.Timeout | null = null;

  constructor(callback: () => void, duration: number) {
    this.callback = callback;
    this.duration = duration;
    this.timeReaming = duration;
  }

  public start() {
    this.clear();
    this.startTime = new Date().getTime();
    this.timerId = setTimeout(this.callback, this.duration);
  }

  public pause() {
    if (!this.startTime) {
      throw new Error("Cannot pause a timer that has not been started");
    }
    this.clear();
    this.timeReaming = this.duration - (new Date().getTime() - this.startTime);
  }

  public resume() {
    this.clear();
    this.startTime = new Date().getTime();
    this.timerId = setTimeout(this.callback, this.timeReaming);
  }

  private clear() {
    if (this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }
  }
}
甜妞爱困 2024-10-05 07:22:48

我认为您不会找到比 clearTimeout 更好的东西了。无论如何,您始终可以稍后安排另一个超时,而不是“恢复”它。

I don't think you'll find anything better than clearTimeout. Anyway, you can always schedule another timeout later, instead 'resuming' it.

街道布景 2024-10-05 07:22:48

如果您有多个要隐藏的 div,您可以使用 setInterval 和多个周期来执行以下操作:

<div id="div1">1</div><div id="div2">2</div>
<div id="div3">3</div><div id="div4">4</div>
<script>
    function hideDiv(elm){
        var interval,
            unit = 1000,
            cycle = 5,
            hide = function(){
                interval = setInterval(function(){
                    if(--cycle === 0){
                        elm.style.display = 'none';
                        clearInterval(interval);
                    }
                    elm.setAttribute('data-cycle', cycle);
                    elm.innerHTML += '*';
                }, unit);
            };
        elm.onmouseover = function(){
            clearInterval(interval);
        };
        elm.onmouseout = function(){
            hide();
        };
        hide();
    }
    function hideDivs(ids){
        var id;
        while(id = ids.pop()){
            hideDiv(document.getElementById(id));
        }
    }
    hideDivs(['div1','div2','div3','div4']);
</script>

If you have several divs to hide, you could use an setInterval and a number of cycles to do like in:

<div id="div1">1</div><div id="div2">2</div>
<div id="div3">3</div><div id="div4">4</div>
<script>
    function hideDiv(elm){
        var interval,
            unit = 1000,
            cycle = 5,
            hide = function(){
                interval = setInterval(function(){
                    if(--cycle === 0){
                        elm.style.display = 'none';
                        clearInterval(interval);
                    }
                    elm.setAttribute('data-cycle', cycle);
                    elm.innerHTML += '*';
                }, unit);
            };
        elm.onmouseover = function(){
            clearInterval(interval);
        };
        elm.onmouseout = function(){
            hide();
        };
        hide();
    }
    function hideDivs(ids){
        var id;
        while(id = ids.pop()){
            hideDiv(document.getElementById(id));
        }
    }
    hideDivs(['div1','div2','div3','div4']);
</script>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文