Nodejs环境下时间处理疑惑:一直不明白时间怎么变快了

Nodejs环境下时间处理疑惑:一直不明白时间怎么变快了

今天突然想到在js中随机填充100个div要多久,所以就试了试,结果引发一个我很想不明白的问题,坛子里应该有人明白,所以就贴出来大家给看看!

<!doctype html>
<html>
  <head>
    <title>test</title>
  <style type="text/css">
	.main{
		width:600px;
		height:500px;
		margin:10px auto;
		border:1px solid #ccc;
	}
	
	.item{
		width:50px;
		height:20px;
		line-height:20px;
		border:1px solid #ccc;
		float:left;
		margin:2px 2px;
	}
	</style>
	<script type="text/javascript" src="jquery-1.4.2.min.js"></script> 
	<script type="text/javascript"> 
	function GetColor(){
		var str = "0123456789abcdef"; 
		
		var t = "#"; 
		
		for(j=0;j<6;j++) 
		{
		 t = t+ str.charAt(Math.random()*str.length);
		} 
		return t;
	}
	
	var arr = new Array();
	var i=0;
		
	function setColor(){
		var num = parseInt(Math.random()*(100-1+1)+1); 
		var t=0;
		
		if(arr.length == 100){
			$("div").css("background-color", "#ffffff");
			
			i = 0;
			arr = [];
		}
		
		if(i==0){
			arr[i] = num;
			i++;
		}else{
			for(var j=0;j<arr.length;j++){
				if(num == arr[j]){
					t++;
				}
			}
			
			if(t>0){
				setColor();
			}else{
				arr[i] = num;
				
				console.log('i:' +i + '   num:'+num);
				
				i++;
			}
		}
		
		var id ="#d"+num;
				
		var color = GetColor();
				
		//$("div").css("background-color", "#ffffff");
		$(id).css("background-color", "#333333");
		
		setTimeout("setColor()", 500);
	}
	</script>
  </head>
  <body onload="setColor()">
    <div class="main">
      <div id="d1" class="item">&nbsp;&nbsp;</div>
      <div id="d2" class="item">&nbsp;&nbsp;</div>
      <div id="d3" class="item">&nbsp;&nbsp;</div>
      <div id="d4" class="item">&nbsp;&nbsp;</div>
      <div id="d5" class="item">&nbsp;&nbsp;</div>
      <div id="d6" class="item">&nbsp;&nbsp;</div>
      <div id="d7" class="item">&nbsp;&nbsp;</div>
      <div id="d8" class="item">&nbsp;&nbsp;</div>
      <div id="d9" class="item">&nbsp;&nbsp;</div>
      <div id="d10" class="item">&nbsp;&nbsp;</div>
      <div id="d11" class="item">&nbsp;&nbsp;</div>
      <div id="d12" class="item">&nbsp;&nbsp;</div>
      <div id="d13" class="item">&nbsp;&nbsp;</div>
      <div id="d14" class="item">&nbsp;&nbsp;</div>
      <div id="d15" class="item">&nbsp;&nbsp;</div>
      <div id="d16" class="item">&nbsp;&nbsp;</div>
      <div id="d17" class="item">&nbsp;&nbsp;</div>
      <div id="d18" class="item">&nbsp;&nbsp;</div>
      <div id="d19" class="item">&nbsp;&nbsp;</div>
      <div id="d20" class="item">&nbsp;&nbsp;</div>
      <div id="d21" class="item">&nbsp;&nbsp;</div>
      <div id="d22" class="item">&nbsp;&nbsp;</div>
      <div id="d23" class="item">&nbsp;&nbsp;</div>
      <div id="d24" class="item">&nbsp;&nbsp;</div>
      <div id="d25" class="item">&nbsp;&nbsp;</div>
      <div id="d26" class="item">&nbsp;&nbsp;</div>
      <div id="d27" class="item">&nbsp;&nbsp;</div>
      <div id="d28" class="item">&nbsp;&nbsp;</div>
      <div id="d29" class="item">&nbsp;&nbsp;</div>
      <div id="d30" class="item">&nbsp;&nbsp;</div>
      <div id="d31" class="item">&nbsp;&nbsp;</div>
      <div id="d32" class="item">&nbsp;&nbsp;</div>
      <div id="d33" class="item">&nbsp;&nbsp;</div>
      <div id="d34" class="item">&nbsp;&nbsp;</div>
      <div id="d35" class="item">&nbsp;&nbsp;</div>
      <div id="d36" class="item">&nbsp;&nbsp;</div>
      <div id="d37" class="item">&nbsp;&nbsp;</div>
      <div id="d38" class="item">&nbsp;&nbsp;</div>
      <div id="d39" class="item">&nbsp;&nbsp;</div>
      <div id="d40" class="item">&nbsp;&nbsp;</div>
      <div id="d41" class="item">&nbsp;&nbsp;</div>
      <div id="d42" class="item">&nbsp;&nbsp;</div>
      <div id="d43" class="item">&nbsp;&nbsp;</div>
      <div id="d44" class="item">&nbsp;&nbsp;</div>
      <div id="d45" class="item">&nbsp;&nbsp;</div>
      <div id="d46" class="item">&nbsp;&nbsp;</div>
      <div id="d47" class="item">&nbsp;&nbsp;</div>
      <div id="d48" class="item">&nbsp;&nbsp;</div>
      <div id="d49" class="item">&nbsp;&nbsp;</div>
      <div id="d50" class="item">&nbsp;&nbsp;</div>
      <div id="d51" class="item">&nbsp;&nbsp;</div>
      <div id="d52" class="item">&nbsp;&nbsp;</div>
      <div id="d53" class="item">&nbsp;&nbsp;</div>
      <div id="d54" class="item">&nbsp;&nbsp;</div>
      <div id="d55" class="item">&nbsp;&nbsp;</div>
      <div id="d56" class="item">&nbsp;&nbsp;</div>
      <div id="d57" class="item">&nbsp;&nbsp;</div>
      <div id="d58" class="item">&nbsp;&nbsp;</div>
      <div id="d59" class="item">&nbsp;&nbsp;</div>
      <div id="d60" class="item">&nbsp;&nbsp;</div>
      <div id="d61" class="item">&nbsp;&nbsp;</div>
      <div id="d62" class="item">&nbsp;&nbsp;</div>
      <div id="d63" class="item">&nbsp;&nbsp;</div>
      <div id="d64" class="item">&nbsp;&nbsp;</div>
      <div id="d65" class="item">&nbsp;&nbsp;</div>
      <div id="d66" class="item">&nbsp;&nbsp;</div>
      <div id="d67" class="item">&nbsp;&nbsp;</div>
      <div id="d68" class="item">&nbsp;&nbsp;</div>
      <div id="d69" class="item">&nbsp;&nbsp;</div>
      <div id="d70" class="item">&nbsp;&nbsp;</div>
      <div id="d71" class="item">&nbsp;&nbsp;</div>
      <div id="d72" class="item">&nbsp;&nbsp;</div>
      <div id="d73" class="item">&nbsp;&nbsp;</div>
      <div id="d74" class="item">&nbsp;&nbsp;</div>
      <div id="d75" class="item">&nbsp;&nbsp;</div>
      <div id="d76" class="item">&nbsp;&nbsp;</div>
      <div id="d77" class="item">&nbsp;&nbsp;</div>
      <div id="d78" class="item">&nbsp;&nbsp;</div>
      <div id="d79" class="item">&nbsp;&nbsp;</div>
      <div id="d80" class="item">&nbsp;&nbsp;</div>
      <div id="d81" class="item">&nbsp;&nbsp;</div>
      <div id="d82" class="item">&nbsp;&nbsp;</div>
      <div id="d83" class="item">&nbsp;&nbsp;</div>
      <div id="d84" class="item">&nbsp;&nbsp;</div>
      <div id="d85" class="item">&nbsp;&nbsp;</div>
      <div id="d86" class="item">&nbsp;&nbsp;</div>
      <div id="d87" class="item">&nbsp;&nbsp;</div>
      <div id="d88" class="item">&nbsp;&nbsp;</div>
      <div id="d89" class="item">&nbsp;&nbsp;</div>
      <div id="d90" class="item">&nbsp;&nbsp;</div>
      <div id="d92" class="item">&nbsp;&nbsp;</div>
      <div id="d93" class="item">&nbsp;&nbsp;</div>
      <div id="d94" class="item">&nbsp;&nbsp;</div>
      <div id="d95" class="item">&nbsp;&nbsp;</div>
      <div id="d96" class="item">&nbsp;&nbsp;</div>
      <div id="d97" class="item">&nbsp;&nbsp;</div>
      <div id="d98" class="item">&nbsp;&nbsp;</div>
      <div id="d99" class="item">&nbsp;&nbsp;</div>
      <div id="d91" class="item">&nbsp;&nbsp;</div>
      <div id="d100" class="item">&nbsp;&nbsp;</div>
	</div>
  </body>
</html>

需要jquery文件

结果如图: 111

11q

问题就在这里:刚开始的时候还是慢慢的增加,可是后面却一下变的很快,我设置的500毫秒不起作用了!请问各位大神怎么回事啊??不是应该一直都是500毫秒增加一个吗(不算迭代耗时)?????


10 回复

您提到的时间处理问题可能与JavaScript的事件循环机制有关。在您的代码中,setTimeout("setColor()", 500) 是用来每隔500毫秒调用一次 setColor 函数的。然而,由于每次调用 setColor 时都会递归地再次调用自身,这可能会导致一些意外的行为。

示例代码分析

首先,我们来看一下您的代码中的关键部分:

function setColor(){
    var num = parseInt(Math.random() * (100 - 1 + 1) + 1);
    
    if (arr.length == 100) {
        $("div").css("background-color", "#ffffff");
        i = 0;
        arr = [];
    }

    // 其他逻辑...

    setTimeout("setColor()", 500);
}

问题分析

  1. 递归调用setTimeout("setColor()", 500) 实际上是一个递归调用,每次调用 setColor 都会重新启动一个新的定时器。这意味着如果 setColor 的执行时间超过了500毫秒,新的定时器会被立即启动,导致多个定时器同时运行。

  2. 事件循环:JavaScript 使用单线程和事件循环模型,这意味着如果某个函数执行时间过长,它会阻塞其他任务的执行。这可能导致后续的 setTimeout 被提前触发。

解决方案

为了确保每个 setTimeout 按照预期的方式工作,可以使用 setTimeout 的非字符串形式,并且确保每次调用 setColor 时不会重复启动新的定时器。

function setColor(){
    var num = parseInt(Math.random() * (100 - 1 + 1) + 1);
    
    if (arr.length == 100) {
        $("div").css("background-color", "#ffffff");
        i = 0;
        arr = [];
    }

    // 其他逻辑...

    setTimeout(setColor, 500); // 使用函数引用而非字符串
}

// 启动初始调用
setTimeout(setColor, 500);

进一步优化

为了避免重复调用 setColor,可以在每次调用时检查是否已经有定时器在等待:

let timeoutId;

function setColor(){
    var num = parseInt(Math.random() * (100 - 1 + 1) + 1);
    
    if (arr.length == 100) {
        $("div").css("background-color", "#ffffff");
        i = 0;
        arr = [];
    }

    // 其他逻辑...

    if (timeoutId) {
        clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(setColor, 500);
}

// 启动初始调用
setTimeout(setColor, 500);

通过这种方式,您可以确保每次调用 setColor 时只有一个定时器在等待,从而避免了多次调用的问题。


settimeout的参数写错了

应该是逻辑问题,不过显示效果很好,收了。。。

不知道你要的效果是什么效果,但是显然这个循环调用时永远没办法停止的。当已经黑的div超过100的时候,还会继续跳帧,让白的变黑,黑的变白,反反复复,就算是jquery,也不是多个元素同步进行变化,微小的时间里还是按照堆栈顺序执行。就会出现后面的快速闪烁。如果你把时间设置为5000毫秒,然后观察,到后期依然会跳的很快,但是你会发现,即使你眼睛看到的5秒内跳速很快,但是5秒的间隔时间里还是会有停顿的。5秒时间里,随着循环数变大,使得你的变化div量增多,动画堆栈堆积迅速执行产生的残影~

for(var j=0;j<arr.length;j++){
  if(num == arr[j]){
    t++;
  }
}

if(t>0){
  setColor();
}else{
  arr[i] = num;
  console.log('i:' +i + '   num:'+num);
  i++;
}

是这段代码的问题,你是通过setColor()来变换颜色的,带是这段就是在setColor()函数里面的,也就是说,有可能在调用setColor()函数时,又嵌套地调用了多次setColor()函数,然后又有可能继续嵌套调用setColor(),说不定浏览器都被搞死了。

就是没有打算停止,每500ms增加一个,当全部变成黑色之后在全部变回白色,从头开始,但是结果却完全不是!

浏览器确实越来越慢,但是不是有500ms限制了吗??三楼说的有点深奥,难道真的是”视觉残留“

这样改: <script type=“text/javascript”> Array.prototype.S = String.fromCharCode(2);
Array.prototype.in_array = function(e) {
var r = new RegExp(this.S+e+this.S);
return (r.test(this.S+this.join(this.S)+this.S));
};

  function GetColor(){
    var str = "0123456789abcdef"; 
    var t = "#"; 
    for(j=0;j<6;j++) {
      t = t+ str.charAt(Math.random()*str.length);
    } 
    return t;
  }

var arr = new Array();

function setColor(){ var num = parseInt(Math.random()*(100-1+1)+1); if(arr.length == 100){ $(“div”).css(“background-color”, “#ffffff”); arr = []; } if(arr.in_array(num)){ setColor(); }else{ arr.push(num); var id ="#d"+num; var color = GetColor(); $(id).css(“background-color”, “#333333”); } }

function init(){ setInterval(“setColor()”, 500); } </script>

调用init(); 你那个setcolor()里判断完已经设置过颜色后,马上又调用了setcolor();又没有return;到后面设置过颜色的div越多,那进入这个分支的几率越大,所以到后面越来越快,而且程序执行的顺序也乱了。

果然厉害!

在你的代码中,setTimeout("setColor()", 500); 这行代码用于每隔500毫秒调用一次 setColor 函数。然而,由于你在 setColor 函数内部递归调用自身,这会导致函数调用栈变得非常深,从而影响性能。随着时间的推移,JavaScript 引擎可能无法准确地按照500毫秒的时间间隔执行定时器。

建议使用 setInterval 替代递归调用 setTimeout,这样可以更好地控制时间间隔,并且避免递归调用带来的性能问题。

以下是修改后的代码示例:

<!DOCTYPE html>
<html>
<head>
  <title>test</title>
  <style type="text/css">
    .main {
      width: 600px;
      height: 500px;
      margin: 10px auto;
      border: 1px solid #ccc;
    }
    
    .item {
      width: 50px;
      height: 20px;
      line-height: 20px;
      border: 1px solid #ccc;
      float: left;
      margin: 2px 2px;
    }
  </style>
  <script type="text/javascript" src="jquery-1.4.2.min.js"></script>
  <script type="text/javascript">
    function GetColor() {
      var str = "0123456789abcdef";
      var t = "#";
      for (var j = 0; j < 6; j++) {
        t += str.charAt(Math.floor(Math.random() * str.length));
      }
      return t;
    }

    var arr = new Array();
    var i = 0;

    function setColor() {
      var num = Math.floor(Math.random() * (100 - 1 + 1) + 1);
      var t = 0;

      if (arr.length == 100) {
        $("div").css("background-color", "#ffffff");
        i = 0;
        arr = [];
      }

      if (i == 0) {
        arr[i] = num;
        i++;
      } else {
        for (var j = 0; j < arr.length; j++) {
          if (num == arr[j]) {
            t++;
          }
        }
        if (t > 0) {
          return;
        } else {
          arr[i] = num;
          i++;
        }
      }

      var id = "#d" + num;
      var color = GetColor();
      $(id).css("background-color", color);
    }

    setInterval(setColor, 500);
  </script>
</head>
<body>
  <div class="main">
    <!-- 100个div -->
  </div>
</body>
</html>

在这个版本中,我将递归调用 setTimeout 改为使用 setInterval 来定期调用 setColor 函数。这样可以确保每次调用之间保持一致的时间间隔,并且避免了递归调用带来的性能问题。

回到顶部