关于setInterval和浏览器选项卡切换的问题

Papaver 2013-08-09 12:10:22
.










<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Question</title>
<style>
.outer {border:1px solid #000; width:520px; height:300px; position:relative; padding:0; overflow:hidden;}
.inner {position:absolute;}
.inner div{border:1px solid red; width:118px; height:138px; margin:5px 5px; float:left;}
</style>
</head>
<body>
<div class="outer">
<div class="inner" id="inner">
<div>1</div><div>1</div><div>1</div><div>1</div>
<div>2</div><div>2</div><div>2</div><div>2</div>
<div>3</div><div>3</div><div>3</div><div>3</div>
<div>4</div><div>4</div><div>4</div><div>4</div>
<div>5</div><div>5</div><div>5</div><div>5</div>
<div>6</div><div>6</div><div>6</div><div>6</div>
<div>7</div><div>7</div><div>7</div><div>7</div>
<div>8</div><div>8</div><div>8</div><div>8</div>
<div>9</div><div>9</div><div>9</div>
</div>
</div>
</body>
<script>
function startScoll(){
var outer = document.getElementById("inner"),timer,mover,tempSub,
divs = outer.getElementsByTagName("div");
outerH = Math.ceil(divs.length/4)*150;

if(divs.length % 4 !== 0){
var temp = 4 - divs.length % 4;
for (var i = 0; i < temp; i++) {
outer.appendChild(document.createElement("div"));
}
}

for(var i = 0; i < 8; i++){
outer.appendChild(divs[i].cloneNode(true));
}

outer.style.top = "0px";
clearInterval(timer);
timer = setInterval(function(){
tempSub = 0;
clearInterval(mover);
mover = setInterval(function(){
outer.style.top = delPx(outer.style.top) - 10 + "px";
tempSub++;
if(tempSub == 15){
clearInterval(mover);
if(delPx(outer.style.top) == -outerH){
outer.style.top = "0px";
return false;
}
}
},30);

},3000);
function delPx(str){
return parseInt(str.substring(0, str.length - 2));
}
}
startScoll();
</script>
</html>

<!--
问题解释:点开页面之后如果选项卡不切换走,焦点一直在这个页面的话,就不会出任何问题。
如果选项卡切换到其它页面,过十几秒、二十秒回来后,发现页面滚动的位置就不准确了。
在其它页面时间比较长,不准确的越厉害,甚至不再回来了。

测试了在谷歌和火狐中都有这个问题。
多测了几遍似乎是:选项卡切走之后,这边的setInterval就停止了。
当切换回来的时候一下把没有执行的函数全部执行了,快速执行中出错了。

当然解决方法可以通过控制top值修复滚动有误的问题,我想问的是:
这个问题是怎么产生的?原理是什么?有没有更好的解决办法?
-->



问题解释:点开页面之后如果选项卡不切换走,焦点一直在这个页面的话,就不会出任何问题。
如果选项卡切换到其它页面,过十几秒、二十秒回来后,发现页面滚动的位置就不准确了。
在其它页面时间比较长,不准确的越厉害,甚至不再回来了。

测试了在谷歌和火狐中都有这个问题。
多测了几遍似乎是:选项卡切走之后,这边的setInterval就停止了。
当切换回来的时候一下把没有执行的函数全部执行了,快速执行中出错了。

当然解决方法可以通过控制top值修复滚动有误的问题,我想问的是:
这个问题是怎么产生的?原理是什么?有没有更好的解决办法?












.
...全文
419 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
fzfei2 2013-08-09
  • 打赏
  • 举报
回复
因为你每 3000 ,可能内层还在操作 我改成判断,内层有没在操作,没有才重新开始


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Question</title>
        <style>
            .outer {border:1px solid #000; width:520px; height:300px; position:relative; padding:0; overflow:hidden;}
            .inner {position:absolute;}
            .inner div{border:1px solid red; width:118px; height:138px; margin:5px 5px; float:left;}
        </style>
    </head>
    <body>
        <div class="outer">
            <div class="inner" id="inner">
                <div>1</div><div>1</div><div>1</div><div>1</div>
                <div>2</div><div>2</div><div>2</div><div>2</div>
                <div>3</div><div>3</div><div>3</div><div>3</div>
                <div>4</div><div>4</div><div>4</div><div>4</div>
                <div>5</div><div>5</div><div>5</div><div>5</div>
                <div>6</div><div>6</div><div>6</div><div>6</div>
                <div>7</div><div>7</div><div>7</div><div>7</div>
                <div>8</div><div>8</div><div>8</div><div>8</div>
                <div>9</div><div>9</div><div>9</div>
            </div>
        </div>
    </body>
    <script>
        function startScoll(){
            var outer = document.getElementById("inner"),timer,mover,tempSub,
                divs = outer.getElementsByTagName("div");
                outerH = Math.ceil(divs.length/4)*150;
 
            if(divs.length % 4 !== 0){
                var temp = 4 - divs.length % 4;
                for (var i = 0; i < temp; i++) {
                    outer.appendChild(document.createElement("div"));
                }
            }
 
            for(var i = 0; i < 8; i++){
                outer.appendChild(divs[i].cloneNode(true));
            }
 
            outer.style.top = "0px";
            clearInterval(timer); 
            var doing=0,bt;
            timer  = setInterval(function(){
            				if(doing || new Date()-bt < 3000 )  return ;
            				bt=new Date();
            				console.info(doing)
                    tempSub = 0;
                    clearInterval(mover);
                    doing=1;
                    mover = setInterval(function(){
                        outer.style.top = delPx(outer.style.top) - 10 + "px";
                        tempSub++;
                         
                        if(tempSub == 15){
                            clearInterval(mover);
                           	doing=0;
                            if(delPx(outer.style.top) == -outerH){
                                outer.style.top = "0px";
                               
                                return false;
                            }
                        }
                    },30);
              
            },100);
              
            function delPx(str){
                return parseInt(str.substring(0, str.length - 2));
            }
        }
        startScoll();
    </script>
</html>
Papaver 2013-08-09
  • 打赏
  • 举报
回复
引用 3 楼 fzfei2 的回复:
DOM的操作也是消耗时间的,理论是讲你的逻辑是没问题的,DOM的操作不顺,卡了下 你的时间就不对了,所以你那样不是很稳定, 可能 切换选项卡 时出再上面说的情况吧
嗯,明白了,谢谢帮助。 马上结贴给分,并且我改了一个更加简单的版本。



<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Question</title>
        <style>
            .outer {border:1px solid #000; width:520px; height:300px; position:relative; padding:0; overflow:hidden;}
            .inner {position:absolute;}
            .inner div{border:1px solid red; width:118px; height:138px; margin:5px 5px; float:left;}
        </style>
    </head>
    <body>
        <div class="outer">
            <div class="inner" id="inner">
                <div>1</div><div>1</div><div>1</div><div>1</div>
                <div>2</div><div>2</div><div>2</div><div>2</div>
                <div>3</div><div>3</div><div>3</div><div>3</div>
                <div>4</div><div>4</div><div>4</div><div>4</div>
                <div>5</div><div>5</div><div>5</div><div>5</div>
                <div>6</div><div>6</div><div>6</div><div>6</div>
                <div>7</div><div>7</div><div>7</div><div>7</div>
                <div>8</div><div>8</div><div>8</div><div>8</div>
                <div>9</div><div>9</div><div>9</div>
            </div>
        </div>
    </body>
    <script>
        function startScoll(){
            var outer = document.getElementById("inner"),timer,mover,tempSub = 15,
                divs = outer.getElementsByTagName("div");
                outerH = Math.ceil(divs.length/4)*150;
 
            if(divs.length % 4 !== 0){
                var temp = 4 - divs.length % 4;
                for (var i = 0; i < temp; i++) {
                    outer.appendChild(document.createElement("div"));
                }
            }
 
            for(var i = 0; i < 8; i++){
                outer.appendChild(divs[i].cloneNode(true));
            }
 
            outer.style.top = "0px";
            clearInterval(timer);
            timer  = setInterval(function(){
				if(tempSub != 15){return false;}
                    tempSub = 0;
                    clearInterval(mover);
                    mover = setInterval(function(){
                        outer.style.top = delPx(outer.style.top) - 10 + "px";
                        tempSub++;
                        
                        if(tempSub == 15){
                            clearInterval(mover);
                            if(delPx(outer.style.top) == -outerH){
                                outer.style.top = "0px";
                                return false;
                            }
                        }
                    },30);
              
            },3000);
              
            function delPx(str){
                return parseInt(str.substring(0, str.length - 2));
            }
        }
        startScoll();
    </script>
</html>

.
fzfei2 2013-08-09
  • 打赏
  • 举报
回复
引用 2 楼 Papaver_Flower 的回复:
还有两个问题: 1.我内层是每30毫秒执行一次,执行15次就会清除定时器,也就是说450毫秒后定时器就会自动被清楚了,而外面需要3000毫秒才执行一次应该不会,外面执行的时候里面还没有停止吧? 2.为什么不切换选项卡的时候,执行就不会出任何错误?
DOM的操作也是消耗时间的,理论是讲你的逻辑是没问题的,DOM的操作不顺,卡了下 你的时间就不对了,所以你那样不是很稳定, 可能 切换选项卡 时出再上面说的情况吧
Papaver 2013-08-09
  • 打赏
  • 举报
回复
引用 1 楼 fzfei2 的回复:
因为你每 3000 ,可能内层还在操作 我改成判断,内层有没在操作,没有才重新开始


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Question</title>
        <style>
            .outer {border:1px solid #000; width:520px; height:300px; position:relative; padding:0; overflow:hidden;}
            .inner {position:absolute;}
            .inner div{border:1px solid red; width:118px; height:138px; margin:5px 5px; float:left;}
        </style>
    </head>
    <body>
        <div class="outer">
            <div class="inner" id="inner">
                <div>1</div><div>1</div><div>1</div><div>1</div>
                <div>2</div><div>2</div><div>2</div><div>2</div>
                <div>3</div><div>3</div><div>3</div><div>3</div>
                <div>4</div><div>4</div><div>4</div><div>4</div>
                <div>5</div><div>5</div><div>5</div><div>5</div>
                <div>6</div><div>6</div><div>6</div><div>6</div>
                <div>7</div><div>7</div><div>7</div><div>7</div>
                <div>8</div><div>8</div><div>8</div><div>8</div>
                <div>9</div><div>9</div><div>9</div>
            </div>
        </div>
    </body>
    <script>
        function startScoll(){
            var outer = document.getElementById("inner"),timer,mover,tempSub,
                divs = outer.getElementsByTagName("div");
                outerH = Math.ceil(divs.length/4)*150;
 
            if(divs.length % 4 !== 0){
                var temp = 4 - divs.length % 4;
                for (var i = 0; i < temp; i++) {
                    outer.appendChild(document.createElement("div"));
                }
            }
 
            for(var i = 0; i < 8; i++){
                outer.appendChild(divs[i].cloneNode(true));
            }
 
            outer.style.top = "0px";
            clearInterval(timer); 
            var doing=0,bt;
            timer  = setInterval(function(){
            				if(doing || new Date()-bt < 3000 )  return ;
            				bt=new Date();
            				console.info(doing)
                    tempSub = 0;
                    clearInterval(mover);
                    doing=1;
                    mover = setInterval(function(){
                        outer.style.top = delPx(outer.style.top) - 10 + "px";
                        tempSub++;
                         
                        if(tempSub == 15){
                            clearInterval(mover);
                           	doing=0;
                            if(delPx(outer.style.top) == -outerH){
                                outer.style.top = "0px";
                               
                                return false;
                            }
                        }
                    },30);
              
            },100);
              
            function delPx(str){
                return parseInt(str.substring(0, str.length - 2));
            }
        }
        startScoll();
    </script>
</html>
还有两个问题: 1.我内层是每30毫秒执行一次,执行15次就会清除定时器,也就是说450毫秒后定时器就会自动被清楚了,而外面需要3000毫秒才执行一次应该不会,外面执行的时候里面还没有停止吧? 2.为什么不切换选项卡的时候,执行就不会出任何错误? .

87,917

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧