javascript:pause setTimeout();

如果我有一个通过var t = setTimeout("dosomething()", 5000)设置的活动超时运行,

有没有办法暂停和恢复?


有什么办法让目前的超时时间剩下吗?
或者我必须在一个variables,当超时设置,存储当前时间,然后我们暂停,现在和之间的区别?

你可以像这样包装window.setTimeout ,我想这与你在问题中提出的build议类似:

 function Timer(callback, delay) { var timerId, start, remaining = delay; this.pause = function() { window.clearTimeout(timerId); remaining -= new Date() - start; }; this.resume = function() { start = new Date(); window.clearTimeout(timerId); timerId = window.setTimeout(callback, remaining); }; this.resume(); } var timer = new Timer(function() { alert("Done!"); }, 1000); timer.pause(); // Do some stuff... timer.resume(); 

像这样的事情应该做的伎俩。

 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 }; } 

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

“停顿”和“恢复”在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); 

Tim Downs的稍微修改版本的答案 。 但是,由于蒂姆回滚我的编辑,我必须自己回答。 我的解决scheme可以使用额外的arguments作为第三(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; 

超时很容易find解决scheme,但间隔是有点棘手。

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

 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”。 超时在5秒后暂停pi_hey。 另一个超时在6秒后恢复pi_hey。 所以pi_hey会触发两次,运行一秒钟,暂停一秒钟,运行一秒钟,然后每2秒继续触发一次。

其他function

  • clearTimeout()clearInterval()

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

  • getTimeLeft()

    pt_hey.getTimeLeft();pi_hey.getTimeLeft(); 将返回多less毫秒,直到下一次触发计划发生。

我需要计算已过去的和剩余的时间来显示进度条。 使用接受的答案并不容易。 对于此任务,“setInterval”比“setTimeout”更好。 所以,我创build了这个可以在任何项目中使用的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(); }); 

我不认为你会发现比clearTimeout更好的东西。 无论如何,你总是可以安排另一个超时,而不是“恢复”它。

你也可以用事件来实现它。

不是计算时差,而是开始并停止收听在后台继续运行的“记号”事件:

 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'); } }; 

如果你使用jQuery,无论如何,看看$ .doTimeout插件。 与setTimeout相比,这是一个巨大的改进,包括让你跟踪你指定的单个stringid的超时时间,并且每次你设置它都不会改变,并且实现简单的取消,查询循环和去抖动,以及更多。 我最常用的jquery插件之一。

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

我需要能够暂停setTimeout()幻灯片般的function。

这是我自己的可执行定时器的实现。 它整合了Tim Down的答案中的评论,如更好的暂停(内核的评论)和一个原型的forms(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(); 

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

使用这个对象代替setTimeout()就像用timer = new Timer( mycallback, 1000 )replacetimerID = setTimeout( mycallback, 1000)一样简单。 然后timer.pause()timer.resume()可用。

你可以看看clearTimeout()

或者根据某个条件被设置时设置的全局variables来暂停。 就像一个button被按下。

  <button onclick="myBool = true" > pauseTimeout </button> <script> var myBool = false; var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000); </script> 

/复活

ES6版使用Class-y语法糖💋

(稍加修改:joinstart())

 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 &amp; 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> 

如果你有几个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>