Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript、ReactJS和在线计时器中的计时器精度_Javascript_Html_Reactjs_Timer_React Hooks - Fatal编程技术网

JavaScript、ReactJS和在线计时器中的计时器精度

JavaScript、ReactJS和在线计时器中的计时器精度,javascript,html,reactjs,timer,react-hooks,Javascript,Html,Reactjs,Timer,React Hooks,我在vanilla JavaScript和ReactJS中都实现了倒计时,当比较两个程序之间的计时器时,我注意到ReactJS中的计时器会随着时间的推移而漂移,与在线时钟相比,香草JavaScript中的计时器保持恒定的速度 具体地说,我首先在我的ReactJS应用程序中运行计时器,然后在我的JS应用程序中运行计时器,然后在在线时钟中运行计时器,最初我的React应用程序的计时器比JS中的计时器提前1s,而JS中的计时器又比在线时钟提前1s。但大约20分钟后,React应用程序的计时器比JS应用

我在vanilla JavaScript和ReactJS中都实现了倒计时,当比较两个程序之间的计时器时,我注意到ReactJS中的计时器会随着时间的推移而漂移,与在线时钟相比,香草JavaScript中的计时器保持恒定的速度

具体地说,我首先在我的ReactJS应用程序中运行计时器,然后在我的JS应用程序中运行计时器,然后在在线时钟中运行计时器,最初我的React应用程序的计时器比JS中的计时器提前1s,而JS中的计时器又比在线时钟提前1s。但大约20分钟后,React应用程序的计时器比JS应用程序的计时器慢了1秒,而JS应用程序的计时器却比在线时钟早了1秒。换句话说,我的React应用程序中的计时器在20分钟后延迟漂移了2秒

下面是我的代码

反应

import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [sessionTime, setSessionTime] = useState(82.5);
  const [breakTime, setBreakTime] = useState(7.5);
  const [clockTime, setClockTime] = useState(82.5 * 60);
  const [current, setCurrent] = useState('session');
  const [isPlaying, setIsPlaying] = useState(false);

  useEffect(() => {
    document.title = convertTime(clockTime);
    if (isPlaying) {
      let startTime = new Date();
      const intervalId = setInterval(() => {
        if (clockTime === 0) {
          setCurrent(current === 'session' ? 'break' : 'session');
          setClockTime(
            current === 'session' ? breakTime * 60 : sessionTime * 60
          );
        } else {
          setClockTime(
            clockTime - (new Date().getTime() - startTime.getTime()) / 1000
          );
          // }
        }
      }, 200);
      return () => {
        clearInterval(intervalId);
      };
    }
  }, [isPlaying, clockTime]);

  const handlePlayClick = () => {
    setIsPlaying(true);
  };

  const handlePauseClick = () => [setIsPlaying(false)];

  const convertTime = (count) => {
    let hours = Math.floor(count / 3600);
    let minutes = Math.floor(count / 60) - hours * 60;
    let seconds = parseFloat(count % 60).toFixed(0);
    if (hours < 10) hours = `0${hours}`;
    if (minutes < 10) minutes = `0${minutes}`;
    if (seconds < 10) seconds = `0${seconds}`;
    return `${hours}:${minutes}:${seconds}`;
  };
  return (
    <div className='App'>
      <span>{convertTime(clockTime)}</span>
      <span>{current}</span>
      {isPlaying ? (
        <button onClick={handlePauseClick}>Pause</button>
      ) : (
        <button onClick={handlePlayClick}>Play</button>
      )}
    </div>
  );
}

export default App;

import React,{useState,useffect}来自“React”;
导入“/App.css”;
函数App(){
const[sessionTime,setSessionTime]=useState(82.5);
const[breakTime,setBreakTime]=使用状态(7.5);
常数[clockTime,setClockTime]=useState(82.5*60);
const[current,setCurrent]=useState('session');
const[isplay,setisplay]=useState(false);
useffect(()=>{
document.title=转换时间(时钟时间);
如果(显示){
让startTime=新日期();
const intervalId=setInterval(()=>{
如果(时钟时间===0){
setCurrent(当前=='session'?'break':'session');
设定时钟时间(
当前==“会话”?中断时间*60:sessionTime*60
);
}否则{
设定时钟时间(
时钟时间-(new Date().getTime()-startTime.getTime())/1000
);
// }
}
}, 200);
return()=>{
clearInterval(intervalId);
};
}
},[ISPlay,时钟时间];
常量handlePlayClick=()=>{
设置显示(真);
};
const handlePauseClick=()=>[setIsPlaying(false)];
const convertTime=(计数)=>{
让小时数=数学楼层(计数/3600);
分钟=数学楼层(计数/60)-小时*60;
让秒数=parseFloat(计数%60).toFixed(0);
如果(小时<10)小时=`0${hours}`;
如果(分钟<10)分钟=`0${minutes}`;
如果(秒<10)秒=`0${seconds}`;
返回`${hours}:${minutes}:${seconds}`;
};
返回(
{convertTime(时钟时间)}
{current}
{isplay(
暂停
) : (
玩
)}
);
}
导出默认应用程序;
香草JS

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Count down timer</title>
  </head>
  <body>
    <span id="time-passed"></span>
    <button id="play">Play</button>
    <button id="pause">Pause</button>
  </body>
  <script src="app.js"></script>
</html>


倒计时
玩
暂停
app.js

const playBtn = document.querySelector('#play');
const pauseBtn = document.querySelector('#pause');

let counter = 82.5 * 60;
let timePassedElem = document.getElementById('time-passed');

const convertTime = (count) => {
  let hours = Math.floor(count / 3600);
  let minutes = Math.floor(count / 60) - hours * 60;
  let seconds = parseFloat(count % 60).toFixed(0);
  if (hours < 10) hours = `0${hours}`;
  if (minutes < 10) minutes = `0${minutes}`;
  if (seconds < 10) seconds = `0${seconds}`;
  return `${hours}:${minutes}:${seconds}`;
};
let intervalId;
playBtn.addEventListener('click', () => {
  let startTime = new Date();
  intervalId = setInterval(() => {
    document.title = convertTime(
      counter + Math.floor((startTime.getTime() - new Date().getTime()) / 1000)
    );
    timePassedElem.innerText = convertTime(
      counter + Math.floor((startTime.getTime() - new Date().getTime()) / 1000)
    );
  }, 200);
});

pauseBtn.addEventListener('click', () => {
  console.log('clicked');
  clearInterval(intervalId);
});

const playBtn=document.querySelector(“#play”);
const pauseBtn=document.querySelector(“#pause”);
设计数器=82.5*60;
让timePassedElem=document.getElementById('time-passed');
const convertTime=(计数)=>{
让小时数=数学楼层(计数/3600);
分钟=数学楼层(计数/60)-小时*60;
让秒数=parseFloat(计数%60).toFixed(0);
如果(小时<10)小时=`0${hours}`;
如果(分钟<10)分钟=`0${minutes}`;
如果(秒<10)秒=`0${seconds}`;
返回`${hours}:${minutes}:${seconds}`;
};
让它有效;
playBtn.addEventListener('单击',()=>{
让startTime=新日期();
intervalId=setInterval(()=>{
document.title=转换时间(
计数器+数学地板((startTime.getTime()-new Date().getTime())/1000)
);
timePassedElem.innerText=convertTime(
计数器+数学地板((startTime.getTime()-new Date().getTime())/1000)
);
}, 200);
});
pauseBtn.addEventListener('单击',()=>{
console.log('clicked');
clearInterval(intervalId);
});

我的问题是,为什么我的ReactJS中的计时器会随时间漂移,而vanilla JS中不会出现这种情况?

我认为你的特效挂钩会在每次渲染时创建一个新的
startTime
。好吧,这似乎解决了这个问题,但当我打开20个YouTube视频时(我正在尝试模拟计时器运行时在其他选项卡上执行的繁重工作)React和JS中的计时器都已停止(我在选项卡标题上看到时间),当我打开选项卡时,页面重新加载,计时器设置为初始状态。我如何防止这种情况发生?事实上,这并没有解决问题。现在React计时器漂移需要更长的时间,但仍然会漂移!!