javascript - setInterval“跳闸”本身并启动第二个间隔计时器
问题描述
我编写了一个选项卡功能,可以在一段时间后在选项卡之间切换,这似乎工作得很好,但是,它已经引起我的注意,有时它会中断。
在查看setInterval
并查看错误本身后,它看起来像setInterval
在 20-30 分钟后,自行跳闸并启动第二个计时器。这会导致同时显示 2 个选项卡。
我在网上读过一些内容,基本上它与 Javascript 是单线程的有关,这只是一个基本缺陷setInterval
,如果它跳闸,它不会重置计时器,它只会创建第二个计时器。是否有为此行程添加错误捕获或运行重复超时功能的更好方法?
jQuery(document).ready(function() {
function autoPlayTabs(tabTitle1, tabTitle2, tabTitle3, tabTitle4, tabContent1, tabContent2, tabContent3, tabContent4, tabLength, tabTitleMobile1, tabTitleMobile2, tabTitleMobile3, tabTitleMobile4) {
var actualTabLength = tabLength * 4;
var tabContainer = jQuery('.elementor-tabs');
var allTabs = jQuery('.elementor-tabs .elementor-tabs-wrapper .elementor-tab-title');
var allContent = jQuery('.elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content');
var initialTabTimer = null;
var tabTimer = null;
tabTitle1.addClass('active'); tabContent1.addClass('active');
console.log('Setting initialTabTimer');
initialTabTimer = setTimeout(function(){
tabTitle1.removeClass('active'); tabContent1.removeClass('active');
tabTitle2.addClass('active'); tabContent2.addClass('active');
console.log("Setting Timeout2");
setTimeout(function(){
tabTitle2.removeClass('active'); tabContent2.removeClass('active');
tabTitle3.addClass('active'); tabContent3.addClass('active');
console.log("Setting Timeout3");
setTimeout(function(){
tabTitle3.removeClass('active'); tabContent3.removeClass('active');
tabTitle4.addClass('active'); tabContent4.addClass('active');
console.log("Executing Timeout3 Function");
}, tabLength);
}, tabLength);
}, tabLength);
console.log("Setting tabTimer");
tabTimer = setInterval(function(){
tabTitle4.removeClass('active'); tabContent4.removeClass('active');
tabTitle1.addClass('active'); tabContent1.addClass('active');
console.log("Setting TimeoutB");
setTimeout(function(){
tabTitle1.removeClass('active'); tabContent1.removeClass('active');
tabTitle2.addClass('active'); tabContent2.addClass('active');
console.log("Setting TimeoutC");
setTimeout(function(){
tabTitle2.removeClass('active'); tabContent2.removeClass('active');
tabTitle3.addClass('active'); tabContent3.addClass('active');
console.log("Setting TimeoutD");
setTimeout(function(){
tabTitle3.removeClass('active'); tabContent3.removeClass('active');
tabTitle4.addClass('active'); tabContent4.addClass('active');
console.log("Executing TimeoutD Function");
}, tabLength);
}, tabLength);
}, tabLength);
}, actualTabLength);
allTabs.click(function() {
if (initialTabTimer !== null) {
clearTimeout(initialTabTimer);
initialTabTimer = null;
console.log("Cleared initialTabTimer");
}
if (tabTimer !== null) {
clearInterval(tabTimer);
tabTimer = null;
console.log("Cleared tabTimer");
} else {
console.log("Did not need to clear tabTimer");
}
allTabs.removeClass('active');
allContent.removeClass('active');
tabContainer.addClass('tabsManual');
});
}
if(homeTabTitle1.length > 0){
console.log("Calling AutoPlayTabs Homepage");
autoPlayTabs(homeTabTitle1,homeTabTitle2,homeTabTitle3,homeTabTitle4,homeTabContent1,homeTabContent2,homeTabContent3,homeTabContent4,homeTabLength);
}
});
下面是一个 console.log,它记录了从它工作到中断到修复自身的每个 setTimeout:
Calling AutoPlayTabs Homepage
Setting initialTabTimer
Setting tabTimer
Setting Timeout2
Setting Timeout3
Executing Timeout3 Function
//This console.log block ran 30 times without error//
Setting TimeoutB
Setting TimeoutC
Setting TimeoutD
Executing TimeoutD Function
//This console.log block ran 30 times without error//
//It Breaks here after a total of 24 minutes//
Setting TimeoutB
Setting TimeoutC
Setting TimeoutD
Setting TimeoutB //For some reason TimeoutB has been fired again
Executing TimeoutD Function
Setting TimeoutC
Setting TimeoutD
Setting TimeoutB
Executing TimeoutD Function
Setting TimeoutC
Setting TimeoutD
Executing TimeoutD Function
//It fixed itself here after 2.4 minutes//
Setting TimeoutB
Setting TimeoutC
Setting TimeoutD
Executing TimeoutD Function
解决方案
如果您只是将逻辑简化为只运行一个间隔,那么您所有的同步问题都会消失
const tabs = [
{title: tabTitle1, content: tabContent1},
{title: tabTitle2, content: tabContent2},
{title: tabTitle3, content: tabContent3},
{title: tabTitle4, content: tabContent4}
];
let curr = 0;
let tab = tabs[curr];
tab.title.addClass("active");
tab.content.addClass("active");
var timerInterval = setInterval(function(){
tab.title.removeClass("active");
tab.content.removeClass("active");
curr = ++curr % tabs.length;
tab = tabs[curr];
tab.title.addClass("active");
tab.content.addClass("active");
}, tabLength);
活生生的例子
jQuery(document).ready(function() {
function autoPlayTabs(tabTitle1, tabTitle2, tabTitle3, tabTitle4, tabContent1, tabContent2, tabContent3, tabContent4, tabLength, tabTitleMobile1, tabTitleMobile2, tabTitleMobile3, tabTitleMobile4) {
var actualTabLength = tabLength * 4;
var tabContainer = jQuery('.elementor-tabs');
var allTabs = jQuery('.elementor-tabs .elementor-tabs-wrapper .elementor-tab-title');
var allContent = jQuery('.elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content');
var initialTabTimer = null;
var tabTimer = null;
const tabs = [
{title: tabTitle1, content: tabContent1},
{title: tabTitle2, content: tabContent2},
{title: tabTitle3, content: tabContent3},
{title: tabTitle4, content: tabContent4}
];
let curr = 0;
let tab = tabs[curr]
tab.title.addClass("active")
tab.content.addClass("active");
var timerInterval = setInterval(function(){
tab.title.removeClass("active")
tab.content.removeClass("active");
curr = ++curr % tabs.length
tab = tabs[curr]
tab.title.addClass("active")
tab.content.addClass("active");
}, tabLength)
allTabs.click(function() {
if (initialTabTimer !== null) {
clearTimeout(initialTabTimer);
initialTabTimer = null;
}
if (tabTimer !== null) {
clearInterval(tabTimer);
tabTimer = null;
}
allTabs.removeClass('active');
allContent.removeClass('active');
tabContainer.addClass('tabsManual');
});
}
if ($("#homeTabTitle1")) {
autoPlayTabs($("#homeTabTitle1"), $("#homeTabTitle2"), $("#homeTabTitle3"), $("#homeTabTitle4"), $("#homeTabContent1"), $("#homeTabContent2"), $("#homeTabContent3"), $("#homeTabContent4"), 1000);
}
});
.active { background-color:red }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="homeTabTitle1">
homeTabTitle1
</div>
<div id="homeTabTitle2">
homeTabTitle2
</div>
<div id="homeTabTitle3">
homeTabTitle3
</div>
<div id="homeTabTitle4">
homeTabTitle4
</div>
<div id="homeTabContent1">
homeTabContent1
</div>
<div id="homeTabContent2">
homeTabContent2
</div>
<div id="homeTabContent3">
homeTabContent3
</div>
<div id="homeTabContent4">
homeTabContent4
</div>
注意我没有连接你的“停止”逻辑,但你需要做的就是clearInterval(timerInterval)
在你的click
处理程序中。
推荐阅读
- python - 约束参数
- javascript - DNS 失败时的 FetchAPI 响应
- serenity-bdd - Serenity 中是否有任何 Edge-Chromium 驱动程序首选项/功能可用于处理“您的连接不是私有的”/SSL 证书错误?
- intellij-idea - IntelliJ IDEA Reopen Project“路径
不存在”错误 - c# - 通过支持/帮助台团队的订单流程记录和跟踪更改
- ios - 未定义符号:_PIXMeterReadingInit 和未定义符号:_PIXAutomatic
- sql - SQL BETWEEN 语句仅返回匹配结果
- excel - Object_Worksheet 的方法范围我只能使第一部分或第二部分工作
- android - 如何将 react-native 应用程序作为模块集成到现有的 android 应用程序中?
- ansible - 在每次播放结束时默认执行 ansible 角色