• JavaScript之关闭轮询定时器(setTimeout/clearTimeout|setInterval/clearInterval)小结


    已知:

      1.1 开启Timeout程序: scope.setTimeout("functionName()" | functionHandle, timeValue) 返回值:timerID

      1.2 关闭Timeout程序: scope.clearTimeout(timerID);

      

      2.1 开启Interval程序: scope.setInterval("functionName()" | functionHandle, timeValue)  返回值:timerID

      2.2 关闭Interval程序: scope.clearInterval(timerID);

    一、背景

      在替实验室小伙伴解决问题过程中,出现了这样一个问题:

        她用网页做了一个轮播图,利用不断地轮询setTimeout + 切换被轮播图片的css属性opacity:0/1来达到轮播效果;

        当网页加载后,图片轮播自动执行;当用户鼠标移动到图片轮播区域上时,立即停止轮播(即 清除 setTimeout定时器),而不是继续轮播图片(使用户看不到想看的图片内容,提高用户体验);

        然而,在全局域中,使用clearTimeout()方法可以实现,但在鼠标触发事件的函数内部调用,却失败,百思不得其解!(这个问题,实际上本文并没有解决!)

        为了解决这个需求,我模拟了这一个过程,并对setTimeout轮询方法与图片轮播的方法进行解耦(分离成为两个函数),然后在封装的轮询定时器Timer中依次调用图片轮播方法和setTimeout方法,同时在轮询过程中,总是记录最近(最后)一次setTimeout方法返回的timerID值,这一点很重要;

        最后:当鼠标滑过目标区域时,通过记录的最后一次timerID和clearTimeeout值来关闭图片轮播整个轮询

        【原理:即关闭最后一次(也是程序执行的最近一次)循环的timeID,使循环停止】

    二、源码

      

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>demo setTimeout & clearTimeout</title>
    </head>
    <body>
        <ul>
            <li><a href="#"><input type="number" value="0"></a></li>
            <li><a href="#"><input type="number" value="1"></a></li>
        </ul>
        <script type="text/javascript">
            var aNodes = document.getElementsByTagName("a");
            var inputNodes = document.getElementsByTagName("input");
            
            //console.log('test:aNodes ' + aNodes.length);
            var changeNum =  function(){
                inputNodes[0].value = parseInt(inputNodes[0].value) + 1;
            };
            
            var a1_timeoutId;
            var timeIds = -1;
            var changeNumByTimer = function(){
                // a1_timeoutId = setTimeout(function(){
                changeNum();
                var timeKey = setTimeout("changeNumByTimer()",1000);
                timeIds = timeKey;
                console.log('test:当前的timeID:' + timeKey);
                // timeIds.push(timeKey);
                // setTimeout(changeNum,1000);
                
                // },1000);
            } 
            changeNumByTimer();
    
            //当鼠标滑过
            aNodes[0].onmouseover = function(){
                console.log('test:aNodes[0].onmouseover:' + "鼠标滑过a链接[0]");
                console.log('test:aNodes[0].onmouseover: timeIds '  + timeIds);
                // for(var i = 0; i < timeIds.length; i++){
                //     // clearTimeout(timeIds[i]);
                //     // console.log('test: 已经关闭了 timeID:' + timeIds[i]);
                //      //clearTimeout(timeIds[timeIds.length-1]);
                //      //console.log('test: 已经关闭了 timeID:' + timeIds[timeIds.length-1]);
                
                // }
                clearTimeout(timeIds);
                console.log('test: 已经关闭了 timeID:' + timeIds);
                
            }
        </script>
    </body>
    </html>

    三、效果

      

      

    四、总结

      1.成功解决了需求的技术问题。

      2.其实并没有解决我们最初的问题:

        2.1 为什么全局域中可以关闭,而在onmouseover(鼠标滑过事件)函数中无法关闭的问题

      

      3.参考文档:

        MDN:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval

      4.欢迎小伙伴交流这一问题~

     

        

  • 相关阅读:
    UIWebView的使用
    ASP.NET自定义简单分页
    匿名方法、委托和Lambda表达式区分演示(图文解释)
    Windows Phone开发(11):常用控件(下)
    来自CodeCanyo的15个优秀移动应用和工具
    JDK、J2EE、J2SE、J2ME概念详解
    配置Eclipse 实现按任意键代码自动补全
    ASP.NET验证码
    asp.net 压缩解压缩zip文件
    HOOK使用:全局键盘钩子
  • 原文地址:https://www.cnblogs.com/johnnyzen/p/7282116.html
Copyright © 2020-2023  润新知