setInterval“跳闸"本身并启动第二个间隔计时器 [英] setInterval 'tripping' itself and starting a 2nd interval timer

查看:38
本文介绍了setInterval“跳闸"本身并启动第二个间隔计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个选项卡功能,可以在一段时间后在选项卡之间切换,这看起来很完美,但是我注意到它有时会中断.

在查看 setInterval 并查看错误本身后,它看起来像 setInterval 20-30 分钟后,自身跳闸并启动第二个计时器.这会导致同时显示 2 个标签.

我在网上阅读了一些内容,基本上它与单线程的 Javascript 相关,这只是 setInterval 的一个基本缺陷,如果它跳闸,它不会重置它只是创建的计时器第二个.无论如何要为此行程添加错误捕获或运行重复超时功能的更好方法?

jQuery(document).ready(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('设置initialTabTimer');initialTabTimer = setTimeout(function(){tabTitle1.removeClass('active');tabContent1.removeClass('active');tabTitle2.addClass('active');tabContent2.addClass('active');控制台日志(设置超时2");设置超时(功能(){tabTitle2.removeClass('active');tabContent2.removeClass('active');tabTitle3.addClass('active');tabContent3.addClass('active');控制台日志(设置超时3");设置超时(功能(){tabTitle3.removeClass('active');tabContent3.removeClass('active');tabTitle4.addClass('active');tabContent4.addClass('active');console.log(正在执行 Timeout3 函数");}, tabLength);}, tabLength);}, tabLength);console.log("设置 tabTimer");tabTimer = setInterval(function(){tabTitle4.removeClass('active');tabContent4.removeClass('active');tabTitle1.addClass('active');tabContent1.addClass('active');控制台日志(设置超时B");设置超时(功能(){tabTitle1.removeClass('active');tabContent1.removeClass('active');tabTitle2.addClass('active');tabContent2.addClass('active');控制台日志(设置超时C");设置超时(功能(){tabTitle2.removeClass('active');tabContent2.removeClass('active');tabTitle3.addClass('active');tabContent3.addClass('active');控制台日志(设置超时D");设置超时(功能(){tabTitle3.removeClass('active');tabContent3.removeClass('active');tabTitle4.addClass('active');tabContent4.addClass('active');console.log(正在执行 TimeoutD 函数");}, tabLength);}, tabLength);}, tabLength);}, 实际标签长度);allTabs.click(function() {if (initialTabTimer !== null) {clearTimeout(initialTabTimer);initialTabTimer = null;console.log(已清除 initialTabTimer");}if (tabTimer !== null) {clearInterval(tabTimer);tabTimer = null;console.log(已清除 tabTimer");} 别的 {console.log(不需要清除tabTimer");}allTabs.removeClass('active');allContent.removeClass('active');tabContainer.addClass('tabsManual');});}if(homeTabTitle1.length > 0){console.log(调用 AutoPlayTabs 主页");autoPlayTabs(homeTabTitle1,homeTabTitle2,homeTabTitle3,homeTabTitle4,homeTabContent1,homeTabContent2,homeTabContent3,homeTabContent4,homeTabLength);}});

下面是从它工作中调用的每个 setTimeout 的 console.log,以打破自我修复:

调用 AutoPlayTabs 主页设置initialTabTimer设置 tabTimer设置超时2设置超时3执行 Timeout3 函数//这个console.log块运行了30次没有错误//设置超时B设置超时C设置超时D执行 TimeoutD 函数//这个console.log块运行了30次没有错误////它在总共 24 分钟后在这里中断//设置超时B设置超时C设置超时DSetting TimeoutB//由于某种原因 TimeoutB 再次被触发执行 TimeoutD 函数设置超时C设置超时D设置超时B执行 TimeoutD 函数设置超时C设置超时D执行 TimeoutD 函数//它在 2.4 分钟后固定在这里//设置超时B设置超时C设置超时D执行 TimeoutD 函数

解决方案

如果您只是将逻辑简化为只运行一个间隔,那么所有同步问题都会迎刃而解

 const tabs = [{标题:tabTitle1,内容:tabContent1},{标题:tabTitle2,内容:tabContent2},{标题:tabTitle3,内容:tabContent3},{标题:tabTitle4,内容:tabContent4}];让当前 = 0;让 tab = tabs[curr];tab.title.addClass(活动");tab.content.addClass(活动");var timerInterval = setInterval(function(){tab.title.removeClass(活动");tab.content.removeClass(活动");curr = ++curr % tabs.length;tab = tabs[curr];tab.title.addClass(活动");tab.content.addClass(活动");}, tabLength);

实例

jQuery(document).ready(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,内容:tabContent1},{标题:tabTitle2,内容:tabContent2},{标题:tabTitle3,内容:tabContent3},{标题:tabTitle4,内容:tabContent4}];让当前 = 0;让 tab = tabs[curr]tab.title.addClass("活动")tab.content.addClass("active");var timerInterval = setInterval(function(){tab.title.removeClass("活动")tab.content.removeClass("active");curr = ++curr % tabs.lengthtab = tabs[当前]tab.title.addClass("活动")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');});}如果($(#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">主页TabTitle1

<div id="homeTabTitle2">主页TabTitle2

<div id="homeTabTitle3">主页TabTitle3

<div id="homeTabTitle4">主页TabTitle4

<div id="homeTabContent1">主页标签内容1

<div id="homeTabContent2">主页TabContent2

<div id="homeTabContent3">主页TabContent3

<div id="homeTabContent4">主页TabContent4

注意我没有连接你的停止"逻辑,但您需要做的就是 click 处理程序中的 clearInterval(timerInterval).

I've coded a tab function that switches between tabs after a set period of time, this seemingly worked perfectly however, it's been bought to my attention that sometimes it breaks.

After looking into setInterval and looking into the error itself it looks like setInterval after 20-30 minutes, trips up on itself and starts a 2nd timer. This causes 2 tabs to show at once.

I've read a bit online where essentially it's to do with Javascript being single threaded and it's just a fundamental flaw with setInterval that if it trips up it doesn't reset the timer it just creates a 2nd one. Is there anyway to add an error catch for this trip or a better way to run a repeating timeout function?

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);
    }
});

Below is a console.log of every setTimeout called from it working, to breaking to fixing itself:

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

解决方案

If you just simplify your logic to only have a single interval running, all your syncronisation problems go away

 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);

Live example

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>

Note I have not hooked up your "stop" logic, but all you need to do is clearInterval(timerInterval) in your click handler.

这篇关于setInterval“跳闸"本身并启动第二个间隔计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆