解决JavaScript计时器变慢的问题

解决JavaScript计时器变慢的问题

本文旨在解决JavaScript中使用`setTimeout`实现的计时器逐渐变慢的问题。我们将分析问题的根源,并提供一种基于系统时间的解决方案,确保计时器的准确性和稳定性。通过修改代码,利用`date`对象获取当前时间,计算时间差,并使用`requestAnimationFrame`优化动画效果,可以创建一个更精确的计时器。

问题分析:setTimeout的局限性

使用setTimeout函数在JavaScript中创建计时器是一种常见的方法。然而,这种方法存在一个固有的问题:setTimeout的回调函数并非在指定的时间间隔后立即执行。它会被放入事件队列,等待线程空闲时才执行。

这意味着,如果主线程繁忙(例如,执行复杂的计算或渲染),回调函数的执行时间可能会延迟。随着时间的推移,这些延迟会累积,导致计时器逐渐变慢。每次更新html元素也会消耗时间,进一步加剧这个问题。

解决方案:基于系统时间的计时器

为了解决setTimeout的局限性,我们可以使用系统时间来计算经过的时间,而不是依赖setTimeout的精确度。这种方法的核心思想是:

立即学习Java免费学习笔记(深入)”;

  1. 在计时器启动时,记录一个起始时间。
  2. 在每次更新计时器显示时,获取当前时间。
  3. 计算当前时间与起始时间的时间差。
  4. 根据时间差更新计时器的显示。

以下是修改后的JavaScript代码:

解决JavaScript计时器变慢的问题

AI建筑知识问答

用人工智能ChatGPT帮你解答所有建筑问题

解决JavaScript计时器变慢的问题22

查看详情 解决JavaScript计时器变慢的问题

var hr = 0; var min = 0; var sec = 0; var count = 0;  var Startbutton = document.getElementById("Start");  var timer = false; var start_time;  function start() {   Startbutton.disabled = true;   timer = true;   start_time = (new Date()).getTime(); // 记录起始时间   stopwatch(); }  function stop() {   timer = false;   start_time = null;   Startbutton.disabled = false; }  function reset() {   timer = false;   start_time = null;   Startbutton.disabled = false;   min = 0;   hr = 0;   sec = 0;   count = 0;    document.getElementById("hr").innerHTML = "00";   document.getElementById("min").innerHTML = "00";   document.getElementById("sec").innerHTML = "00";   document.getElementById("count").innerHTML = "00"; }  function stopwatch() {   var now = (new Date()).getTime(); // 获取当前时间   var diff = now - start_time; // 计算时间差    if (timer) {     var str_time = (new Date(diff).toISOString().slice(11, 23)); // 将时间差转换为HH:MM:SS.MS格式      var hrString = "" + str_time.substring(0, 2);     var minString = "" + str_time.substring(3, 5);     var secString = "" + str_time.substring(6, 8);     var countString = "" + str_time.substring(9, 11);      document.getElementById("hr").innerHTML = hrString;     document.getElementById("min").innerHTML = minString;     document.getElementById("sec").innerHTML = secString;     document.getElementById("count").innerHTML = countString;     requestAnimationFrame(stopwatch); // 使用requestAnimationFrame   } }

代码解释:

  • start_time: 在start()函数中,我们使用 (new Date()).getTime() 获取当前时间戳,并将其存储在 start_time 变量中。
  • now = (new Date()).getTime(): 在 stopwatch() 函数中,我们使用 (new Date()).getTime() 获取当前时间戳。
  • diff = now – start_time: 计算当前时间与起始时间的时间差。
  • new Date(diff).toISOString().slice(11, 23): 将时间差转换为 HH:MM:SS.MS 格式的字符串。toISOString() 方法返回UTC格式的日期字符串,我们使用 slice(11, 23) 截取时间部分。
  • requestAnimationFrame(stopwatch): 使用 requestAnimationFrame 函数来安排下一次 stopwatch() 函数的执行。requestAnimationFrame 的优点在于它会根据浏览器的刷新率进行优化,从而提供更平滑的动画效果,并且避免不必要的CPU占用。

HTML代码(保持不变):

<html lang="en">  <head>     <meta charset="UTF-8" />     <meta http-equiv="X-UA-Compatible" content="IE=edge" />     <meta name="viewport" content="width=device-width, initial-scale=1.0" />     <title>Stopwatch</title>     <link rel="stylesheet" href="style.css" /> </head>  <body>     <div id="container">         <div id="time">             <span class="digit" id="hr">00</span>             <span class="txt">Hr</span>              <span class="digit" id="min">00</span>             <span class="txt">Min</span>              <span class="digit" id="sec">00</span>             <span class="txt">Sec</span>               <span class="digit" id="count">00</span>          </div>         <div id="btn-container">             <button class="btn" id="Start" onclick="start()">Start</button>             <button class="btn" id="Stop" onclick="stop()">Stop</button>             <button class="btn" id="Reset" onclick="reset()">Reset</button>         </div>     </div>       <script src="script.JS"></script> </body>  </html>

总结

通过使用系统时间计算时间差,并结合requestAnimationFrame函数,我们可以创建一个更精确、更稳定的JavaScript计时器。这种方法避免了setTimeout的局限性,确保计时器能够准确地反映经过的时间。在实际应用中,可以根据需要调整代码,例如,可以添加暂停功能,或者将计时器显示为不同的格式。

暂无评论

发送评论 编辑评论


				
上一篇
下一篇
text=ZqhQzanResources