[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.欢迎小伙伴交流这一问题~

 

 

    

posted @ 2017-08-03 22:02  千千寰宇  阅读(11162)  评论(0编辑  收藏  举报