切换选项卡后 setInterval() 行为很奇怪
setInterval() acts weird after switching tabs
我使用 javascript 创建了一个效果来显示我项目中的热门类别。
正如您在上图中所见,它运行良好。但是在 运行 一段时间后;如果用户离开此页面并切换到另一个选项卡并在一段时间后返回此页面,那么它就会开始表现得很奇怪。
下面是我用来实现此效果的代码。
var curCat = 0;
var cats = [
"<a href='/search/?cat=1'>Animals</a>",
"<a href='/search/?cat=2'>Graffiti</a>",
"<a href='/search/?cat=3'>Figures</a>",
"<a href='/search/?cat=6'>Landscape</a>",
"<a href='/search/?cat=7'>Portrait</a>",
"<a href='/search/?cat=9'>Other</a>"
];
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setInterval(function() {
$(catDisplay).fadeOut();
setTimeout(function() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
}, 400);
}, 3000);
}
$(document).ready(function() {
catSlider();
});
是什么导致了这个问题?我错过了什么?
Timers get throttled back when the tab doesn't have focus (and many other odd games, such as being accelerated when focus returns), so your setInterval
and your setTimeout
可能会不同步。
相反,只需使用 setTimeout
,其中每个动作(淡出和淡入)都会触发下一个动作:
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
function fadeOut() {
$(catDisplay).fadeOut();
setTimeout(fadeIn, 400);
}
function fadeIn() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setTimeout(fadeOut, 3000);
}
setTimeout(fadeOut, 3000);
}
And/or 您可能会考虑 fadeOut
和 fadeIn
可以触发的回调,特别是在 fadeOut
:
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
function fadeOut() {
$(catDisplay).fadeOut(fadeIn); // ***
}
function fadeIn() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setTimeout(fadeOut, 3000);
}
setTimeout(fadeOut, 3000);
}
旁注:如果你愿意,可以替换
if (++curCat >= cats.length) {
curCat = 0;
}
和
curCat = (curCat + 1) % cats.length;
3000 毫秒间隔可能 运行 比 400 毫秒超时快,因为浏览器会在您返回选项卡后尝试同步间隔。要解决此问题,您可以使用延迟循环,例如:
const timer = ms => new Promise(res => setTimeout(res, ms));
(async function() {
while(true) {
hideCurrent();
await timer(400);
showNext();
await timer(2600);
}
})()
我使用 javascript 创建了一个效果来显示我项目中的热门类别。
正如您在上图中所见,它运行良好。但是在 运行 一段时间后;如果用户离开此页面并切换到另一个选项卡并在一段时间后返回此页面,那么它就会开始表现得很奇怪。
下面是我用来实现此效果的代码。
var curCat = 0;
var cats = [
"<a href='/search/?cat=1'>Animals</a>",
"<a href='/search/?cat=2'>Graffiti</a>",
"<a href='/search/?cat=3'>Figures</a>",
"<a href='/search/?cat=6'>Landscape</a>",
"<a href='/search/?cat=7'>Portrait</a>",
"<a href='/search/?cat=9'>Other</a>"
];
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setInterval(function() {
$(catDisplay).fadeOut();
setTimeout(function() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
}, 400);
}, 3000);
}
$(document).ready(function() {
catSlider();
});
是什么导致了这个问题?我错过了什么?
Timers get throttled back when the tab doesn't have focus (and many other odd games, such as being accelerated when focus returns), so your setInterval
and your setTimeout
可能会不同步。
相反,只需使用 setTimeout
,其中每个动作(淡出和淡入)都会触发下一个动作:
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
function fadeOut() {
$(catDisplay).fadeOut();
setTimeout(fadeIn, 400);
}
function fadeIn() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setTimeout(fadeOut, 3000);
}
setTimeout(fadeOut, 3000);
}
And/or 您可能会考虑 fadeOut
和 fadeIn
可以触发的回调,特别是在 fadeOut
:
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
function fadeOut() {
$(catDisplay).fadeOut(fadeIn); // ***
}
function fadeIn() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setTimeout(fadeOut, 3000);
}
setTimeout(fadeOut, 3000);
}
旁注:如果你愿意,可以替换
if (++curCat >= cats.length) {
curCat = 0;
}
和
curCat = (curCat + 1) % cats.length;
3000 毫秒间隔可能 运行 比 400 毫秒超时快,因为浏览器会在您返回选项卡后尝试同步间隔。要解决此问题,您可以使用延迟循环,例如:
const timer = ms => new Promise(res => setTimeout(res, ms));
(async function() {
while(true) {
hideCurrent();
await timer(400);
showNext();
await timer(2600);
}
})()