Javascript 当标签未激活时,setInterval 无法正常工作
Javascript setInterval doesn't work correctly when tab is not active
function initTimer(timeLeft) {
var Me = this,
TotalSeconds = 35,
Seconds = Math.floor(timeLeft);
var x = window.setInterval(function() {
var timer = Seconds;
if(timer === -1) { clearInterval(x); return; }
$('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
Seconds--;
},1000);
}
我有这个代码。一切正常,当此选项卡在浏览器中处于活动状态时,但是当我更改选项卡并稍后在选项卡中更改 return 时出现问题。更准确地说,它错误地显示了时间。
我也尝试过 setTimeout,但问题是一样的。
我的一个想法是:HTML5 Web Workers...
但是这里还有一个问题...浏览器支持。
有人可以帮忙解决这个问题吗?
如何编写 setInterval,即使选项卡未处于活动状态,它也能正常工作
使用Date
对象计算时间。不要依赖计时器在您要求时触发(它们不是实时的),因为您唯一的保证是它不会在您要求之前触发。它可能会在 很久以后 触发,尤其是对于非活动选项卡。尝试这样的事情:
function initTimer(periodInSeconds) {
var end = Date.now() + periodInSeconds * 1000;
var x = window.setInterval(function() {
var timeLeft = Math.floor((end - Date.now()) / 1000);
if(timeLeft < 0) { clearInterval(x); return; }
$('#div').html('00:' + (timeLeft < 10 ? '0' + timeLeft : timeLeft));
},200);
}
initTimer(10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div"></div>
请注意,通过更频繁地检查它,我们可以确保它永远不会偏离太多。
JavaScript 计时器不可靠,即使选项卡处于活动状态。他们只保证至少已经过了您指定的时间;不能保证正好那个时间,甚至接近它的时间,已经过去了。
要解决这个问题,每当间隔触发时,记下现在的时间。您实际上只需要跟踪两个时间:当前时间和前一个间隔触发的时间。通过从当前报价的时间减去前一个报价的时间,您可以知道实际上在两者之间经过了多少时间,以及运行您的相应计算。
下面是类似这样的东西的基本轮廓:
function initTimer(timeLeft) {
var Me = this,
TotalSeconds = 35,
Seconds = Math.floor(timeLeft),
CurrentTime = Date.now(),
PreviousTime = null;
var x = window.setInterval(function() {
var timer = Seconds,
timePassed;
PreviousTime = CurrentTime;
CurrentTime = Date.now();
timePassed = CurrentTime - PreviousTime;
if(timer < 0) { clearInterval(x); return; }
$('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
Seconds = Seconds - timePassed;
},1000);
}
function initTimer(timeLeft) {
var Me = this,
TotalSeconds = 35,
Seconds = Math.floor(timeLeft);
var x = window.setInterval(function() {
var timer = Seconds;
if(timer === -1) { clearInterval(x); return; }
$('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
Seconds--;
},1000);
}
我有这个代码。一切正常,当此选项卡在浏览器中处于活动状态时,但是当我更改选项卡并稍后在选项卡中更改 return 时出现问题。更准确地说,它错误地显示了时间。
我也尝试过 setTimeout,但问题是一样的。
我的一个想法是:HTML5 Web Workers...
但是这里还有一个问题...浏览器支持。
有人可以帮忙解决这个问题吗? 如何编写 setInterval,即使选项卡未处于活动状态,它也能正常工作
使用Date
对象计算时间。不要依赖计时器在您要求时触发(它们不是实时的),因为您唯一的保证是它不会在您要求之前触发。它可能会在 很久以后 触发,尤其是对于非活动选项卡。尝试这样的事情:
function initTimer(periodInSeconds) {
var end = Date.now() + periodInSeconds * 1000;
var x = window.setInterval(function() {
var timeLeft = Math.floor((end - Date.now()) / 1000);
if(timeLeft < 0) { clearInterval(x); return; }
$('#div').html('00:' + (timeLeft < 10 ? '0' + timeLeft : timeLeft));
},200);
}
initTimer(10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div"></div>
请注意,通过更频繁地检查它,我们可以确保它永远不会偏离太多。
JavaScript 计时器不可靠,即使选项卡处于活动状态。他们只保证至少已经过了您指定的时间;不能保证正好那个时间,甚至接近它的时间,已经过去了。
要解决这个问题,每当间隔触发时,记下现在的时间。您实际上只需要跟踪两个时间:当前时间和前一个间隔触发的时间。通过从当前报价的时间减去前一个报价的时间,您可以知道实际上在两者之间经过了多少时间,以及运行您的相应计算。
下面是类似这样的东西的基本轮廓:
function initTimer(timeLeft) {
var Me = this,
TotalSeconds = 35,
Seconds = Math.floor(timeLeft),
CurrentTime = Date.now(),
PreviousTime = null;
var x = window.setInterval(function() {
var timer = Seconds,
timePassed;
PreviousTime = CurrentTime;
CurrentTime = Date.now();
timePassed = CurrentTime - PreviousTime;
if(timer < 0) { clearInterval(x); return; }
$('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
Seconds = Seconds - timePassed;
},1000);
}