如果我有通过var t = setTimeout("dosomething()", 5000)
无论如何暂停并恢复它?
<小时/> 有没有办法让剩余时间在当前超时? 或者我必须在变量中,当设置超时时,存储当前时间,然后我们暂停,从而获得现在和之间的差异?
答案 0 :(得分:238)
你可以像这样包裹window.setTimeout
,我认为这与你在问题中建议的相似:
function Timer(callback, delay) {
var timerId, start, remaining = delay;
this.pause = function() {
window.clearTimeout(timerId);
remaining -= Date.now() - start;
};
this.resume = function() {
start = Date.now();
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();
答案 1 :(得分:16)
这样的事情应该可以解决问题。
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 };
}
答案 2 :(得分:8)
没有。您需要取消它(clearTimeout
),测量自启动以来的时间并使用新时间重新启动它。
答案 3 :(得分:7)
Tim Downs answer的略微修改版本。但是,自从Tim rolled back编辑以来,我自己就回答这个问题。我的解决方案可以使用额外的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;
答案 4 :(得分:6)
Timeout很容易找到解决方案,但Interval有点棘手。
我想出了以下两个类来解决这个问题:
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);
此示例设置一个可暂停的Interval(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();
将返回计划发生下一次触发之前的毫秒数。
答案 5 :(得分:6)
“暂停”和“恢复”在setTimeout
的上下文中并没有多大意义,这是一次性事物。你的意思是setInterval
?如果是,不,你不能暂停它,你只能取消它(clearInterval
),然后再重新安排它。详情Timers section中所有这些内容的详细信息。
// 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);
答案 6 :(得分:2)
我需要计算显示进度条的已用时间和剩余时间。使用接受的答案并不容易。对于此任务,'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();
});
答案 7 :(得分:2)
/恢复
使用Class-y syntactic sugar的ES6版本
(略微修改:添加了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>
答案 8 :(得分:1)
你也可以用事件来实现它。
不是计算时差,而是开始和停止收听一直在后台运行的'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');
}
};
答案 9 :(得分:1)
如果您无论如何使用jquery,请查看$.doTimeout插件。这比setTimeout有了很大的改进,包括让你用你指定的单个字符串id跟踪你的超时,并且每次设置它都不会改变,并实现简单的取消,轮询循环和放大。去抖等等。我最常用的jquery插件之一。
不幸的是,它不支持暂停/恢复开箱即用。为此,您需要包装或扩展$ .doTimeout,可能与接受的答案类似。
答案 10 :(得分:1)
您可以查看clearTimeout()
或暂停,具体取决于遇到某个条件时设置的全局变量。就像按下按钮一样。
<button onclick="myBool = true" > pauseTimeout </button>
<script>
var myBool = false;
var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000);
</script>
答案 11 :(得分:1)
我需要能够暂停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()
。
答案 12 :(得分:1)
function delay (ms) { return new Promise(resolve => setTimeout(resolve, s)); }
“异步”工作演示位于: site zarsoft.info
答案 13 :(得分:1)
基于评分最高的答案的打字稿实现
/** 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;
}
}
}
答案 14 :(得分:0)
我认为你找不到比clearTimeout更好的东西。无论如何,你总是可以在以后安排另一次超时,而不是'恢复'它。
答案 15 :(得分:0)
您可以像下面那样在服务器端(Node.js)暂停setTimeout
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)
答案 16 :(得分:0)
如果有人想要尊敬的@SeanVieira here 分享的 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;
}
答案 17 :(得分:-1)
如果要隐藏多个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>