var t = setTimeout("dosomething()", 5000)
で設定されたアクティブなタイムアウトが実行されている場合、
とにかく一時停止して再開する方法はありますか?
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();
このような何かがトリックを行う必要があります。
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
)。開始してからの時間を測定し、新しい時間で再起動します。
Tim Downsのわずかに変更されたバージョン answer 。しかし、ティム ロールバック 私の編集なので、私は自分でこれに答えなければなりません。私のソリューションでは、追加のarguments
を3番目(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;
「一時停止」と「再開」は、one-offである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);
タイムアウトは簡単に解決策を見つけることができましたが、間隔は少し複雑でした。
この問題を解決するために、次の2つのクラスを思いつきました。
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);
この例では、2秒後に「hey」というアラートがスケジュールされる一時停止可能なタイムアウト(pt_hey)を設定します。別のタイムアウトは、1秒後にpt_heyを一時停止します。 3番目のタイムアウトは、2秒後にpt_heyを再開します。 pt_heyは1秒間実行され、1秒間停止してから実行を再開します。 pt_heyは3秒後にトリガーします。
トリッキーな間隔のために
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)を設定して、2秒ごとにコンソールに「hello world」を書き込みます。タイムアウトは、5秒後にpi_heyを一時停止します。 6秒後に別のタイムアウトがpi_heyを再開します。したがって、pi_heyは2回トリガーし、1秒間実行し、1秒間停止し、1秒間実行してから、2秒ごとにトリガーを継続します。
clearTimeout()およびclearInterval()
pt_hey.clearTimeout();
およびpi_hey.clearInterval();
は、タイムアウトと間隔をクリアする簡単な方法として機能します。
getTimeLeft()
pt_hey.getTimeLeft();
およびpi_hey.getTimeLeft();
は、次のトリガーの発生がスケジュールされるまでのミリ秒数を返します。
/ revive
Class-y構文糖を使用した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>
進行状況バーを表示するには、経過時間と残り時間を計算する必要がありました。受け入れられた答えを使うのは簡単ではありませんでした。このタスクでは、「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();
});
clearTimeout() を調べることができます
または、特定の条件が満たされたときに設定されるグローバル変数に応じて一時停止します。ボタンが押されたように。
<button onclick="myBool = true" > pauseTimeout </button>
<script>
var myBool = false;
var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000);
</script>
イベントで実装することもできます。
時差を計算する代わりに、バックグラウンドで実行し続ける「ティック」イベントのリッスンを開始および停止します。
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');
}
};
スライドショーのような機能のためにsetTimeout()を一時停止できるようにする必要がありました。
ここに一時停止可能なタイマーの独自の実装があります。一時停止の改善(カーネルのコメント)やプロトタイピングの形式(Umur Gedikのコメント)など、Tim Downの回答に見られるコメントを統合します。
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()
が利用可能になります。
とにかくjqueryを使用している場合は、 $。doTimeout プラグインを確認してください。これは、指定した単一の文字列IDでタイムアウトを追跡でき、設定するたびに変更されず、簡単なキャンセル、ポーリングループおよびデバウンスを実装できるなど、setTimeoutよりも大幅に改善されています。もっと。私の最もよく使われるjqueryプラグインの1つ。
残念ながら、すぐに使用できる一時停止/再開はサポートされていません。このためには、おそらく受け入れられた答えと同様に、$。doTimeoutをラップまたは拡張する必要があります。
clearTimeout より良いものはないと思います。とにかく、いつでも別のタイムアウトをスケジュールして、代わりに「再開」することができます。