liusaint1992的专栏

恒者行远,思者常新

javascript两种禁止一个函数没有运行结束时就再次调用的方法

javascript写函数的时候,常常遇到一个函数还没有运行完就再次调用同一个函数的情况,而这种情况下就可能发生一些未预期的结果。


之前在javascript论坛上回答过一个问题,JS中图片抖动问题 

它这个图片,mouseover时间会让它抖动一阵子,然后回到原来的位置,但是如果在它还没有抖动结束的时候,再去触发mouseover的时候,就会在原来的函数还没有执行完恢复到原地的时候再次执行,从而导致最终图片偏离原位。


问题代码:
<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
	<style type="text/css">
		img{width:150px; height:150px; position:absolute; top:50px; left:300px; } 
	</style>
	<script>
		window.onload = function(){
			function getStyle(obj,attr){
				return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr];
			}
			function shake(obj,attr,endFn){
				var arr = [];
				for(var i=20;i>0;i-=2){
					arr.push(i,-i);
				}
				arr.push(0);
				var num = 0;
				var origin = parseInt(getStyle(obj,attr));
				obj.shake = setInterval(function(){
					obj.style[attr] = origin + arr[num] + 'px';
					num++;
					if(num == arr.length){
						clearInterval(obj.shake);
						endFn && endFn();
					}
				},50)
			}
			var img = document.getElementsByTagName("img")[0];
			img.onmouseover = function(){
				shake(this,'top');
			}
		}
	</script>
</head>
<body>
	<img src="http://avatar.csdn.net/2/9/2/3_liusaint1992.jpg">
</body>
</html>

只要保证一次函数没有执行结束之前不再次执行该函数就可以了。 这里给出两种方法。

方法一,用全局变量标识函数执行状态。

使用一个全局变量做标识,shaking = false。 我们执行函数之前先判断  if(shaking == false){return;}shaking = true  ,  然后在函数执行结束的时候加一句:shaking = false。标识函数没有在执行。

具体代码:

                window.onload = function(){
			function getStyle(obj,attr){
				return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr];
			}
		        var shaking = false;
			function shake(obj,attr,endFn){
				if(shaking == true){
					return;
				}
				shaking = true;
				var arr = [];
				for(var i=20;i>0;i-=2){
					arr.push(i,-i);
				}
				arr.push(0);
				var num = 0;
				var origin = parseInt(getStyle(obj,attr));
				obj.shake = setInterval(function(){
					obj.style[attr] = origin + arr[num] + 'px';
					num++;
					if(num == arr.length){
						clearInterval(obj.shake);
						endFn && endFn();
						shaking = false;
					}
				},50)

			}
			var img = document.getElementsByTagName("img")[0];
			img.onmouseover = function(){
				shake(this,'top');
			}
		}


可是这样毕竟引了了一个新的全局变量,不到迫不得已的时候,我是不想引用新的全局变量的。 那么有没有不用全局变量的方法来阻止函数没执行结束的时候就再次被执行呢?最近写一个控件的时候,突然想到一种新的方法。 用起来也比较溜。


方法二:用销毁函数然后再恢复函数的方法阻止函数运行。  
原理是,如果我们在执行这个函数的时候,把这个函数销毁了,函数执行结束的时候再将这个函数恢复。   在函数执行过程中,这个函数名都不存在了,自然无法调用。   一执行该函数,就给该函数做一个备份,然后销毁该函数,函数主体执行结束用备份的函数恢复我们销毁的函数。

示例代码:
       function a(){
            var b = a;//备份
            a = null;//销毁
            console.log('i am in a ');
            a = b;//恢复
        }

运用到上面的案例中:

关键代码:
     // var shaking = false;
     function shake(obj,attr,endFn){
        // if(shaking == true){
        //     return;
        // }
        // shaking = true;
        var backup = shake;//备份
        shake = null;//销毁
        var arr = [];
        for(var i=20;i>0;i-=2){
            arr.push(i,-i);
        }
        arr.push(0);
        var num = 0;
        var origin = parseInt(getStyle(obj,attr));
        obj.shake = setInterval(function(){
            obj.style[attr] = origin + arr[num] + 'px';
            num++;
            if(num == arr.length){
                clearInterval(obj.shake);
                endFn && endFn();
                // shaking = false;
                shake = backup;//抖动结束之后恢复
            }
        },50)
 
    }

经测试,两种方法实现了同样的效果!
不知道还没有其他更好的方法可以实现同样的效果,甚至有更高的效率。 欢迎留言交流。


阅读更多
版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/liusaint1992/article/details/49933971
个人分类: JavaScript 前端
上一篇根据卫星仰角和方位角使用html5绘制天空图(投影图)
下一篇百度地图API一:百度地图上循环显示标注点。使用闭包循环加载点击事件
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭