|
27 | 27 | } |
28 | 28 | </script> |
29 | 29 |
|
30 | | -点击后,会发现,并不是过100毫秒执行的;如果去掉for循环,那是差不多的; |
| 30 | +点击后,会发现,并不是过100毫秒执行的;如果去掉for循环,那是差不多的; |
| 31 | + |
| 32 | +# 重复定时器 setInterval |
| 33 | + |
| 34 | +使用 setInterval() 创建的定时器确保了定时器代码规则地插入队列中。这个方式的问题在于,定时器代码可能在代码再次被添加到队列之前还没有完成执行,结果导致定时器代码连续运行好几次,而之间没有任何停顿。 |
| 35 | + |
| 36 | +幸好,JavaScript 引擎够聪明,能避免这个问题。 |
| 37 | + |
| 38 | +当使用setInterval() 时, |
| 39 | + |
| 40 | +- 1、仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。 |
| 41 | + |
| 42 | +这确保了定时器代码加入到队列中的最小时间间隔为指定间隔。 |
| 43 | + |
| 44 | +但是由此引发了setInterval 定时器规则有两个问题: |
| 45 | + |
| 46 | +- 1、某些间隔会被跳过; |
| 47 | +- 2、多个定时器的代码执行之间的间隔可能会比预期的小; |
| 48 | + |
| 49 | +因为规则是:**仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。** |
| 50 | + |
| 51 | +如果设置一个重复定时器 (setInterval); 处理的时间为300毫秒;但是间隔时间是200毫秒;间隔时间小于单次定时器内代码的处理时间;就会同时出现跳过间隔且连续运行定时器代码的情况。(**队列中已经有一次相同的定时器时,第二次添加会被忽略**) |
| 52 | + |
| 53 | + |
| 54 | +高程三的例子: |
| 55 | + |
| 56 | +假设,某个 onclick 事件处理程序使用 setInterval() 设置了一个 200ms 间隔的重复定时器。如果事件处理程序花了 300ms多一点的时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过间隔且连续运行定时器代码的情况。 |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | +这个例子中的第 1 个定时器是在 205ms 处添加到队列中的,但是直到过了 300ms 处才能够执行。当执行这个定时器代码时,在 405ms处又给队列添加了另外一个副本。在下一个间隔,即 605ms 处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。所以在这个时间点上的定时器代码不会被添加到队列中。 |
| 61 | + |
| 62 | +**结果在 5ms处添加的定时器代码结束之后,405ms 处添加的定时器代码就立刻执行。** |
| 63 | + |
| 64 | +##### 解决的办法 |
| 65 | + |
| 66 | +使用链式 setTimeout() 调用 |
| 67 | + |
| 68 | + setTimeout(function(){ |
| 69 | + //处理中 |
| 70 | + setTimeout(arguments.callee, 400); |
| 71 | + }, 500); |
| 72 | + |
| 73 | +- 在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。 |
| 74 | +- 而且,它可以保证在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行。这个模式主要用于重复定时器, |
| 75 | + |
| 76 | + <!doctype html> |
| 77 | + <html> |
| 78 | + <head> |
| 79 | + <meta charset="UTF-8"> |
| 80 | + <title>Document</title> |
| 81 | + <link rel="stylesheet" href="test.css"/> |
| 82 | + <style> |
| 83 | + #test{ |
| 84 | + width: 200px;height: 200px;background-color: #002d32; |
| 85 | + position: absolute; |
| 86 | + top: 300px; |
| 87 | + left: 20px; |
| 88 | + } |
| 89 | + </style> |
| 90 | + </head> |
| 91 | + <body> |
| 92 | + <div id="test">2222222222</div> |
| 93 | + <script> |
| 94 | + var div = document.getElementById("test"); |
| 95 | + var left; |
| 96 | + var timer=setTimeout(function(){ |
| 97 | + //处理中 |
| 98 | + left = parseFloat(window.getComputedStyle(div,null).left)+5; |
| 99 | + console.log(left); |
| 100 | + div.style.left = left + "px"; |
| 101 | + if (left < 200) { |
| 102 | + setTimeout(arguments.callee, 500); |
| 103 | + console.log("star agin "); |
| 104 | + }else{ |
| 105 | + console.log("clear Timeout"); |
| 106 | + clearTimeout(timer); |
| 107 | + } |
| 108 | + }, 10); |
| 109 | + </script> |
| 110 | + </body> |
| 111 | + </html> |
| 112 | + |
| 113 | +JavaScript 动画中使用这个模式很常见。 |
0 commit comments