javascript react-刷新屏幕后倒计时计时器(轻微不同步)问题

zed5wv10  于 2023-01-04  发布在  Java
关注(0)|答案(1)|浏览(231)

我有一个拍卖网站MERN堆栈与socket.io,我似乎有这个无法解决的问题,我认为这是有关浏览器和基本的JS

流量

  • 每当一个产品是由管理员添加,套接字广播它与所有的细节(包括时间)给所有的客户端。
  • 客户可以出价购买。
  • 如果用户刷新屏幕,则向套接字请求最新产品时间,并从该时间开始倒计时。

一切都很好,除了有时React倒计时是滞后0.5秒至1秒后,每当页面刷新(请注意,问题不会发生时,在新的标签打开相同的拍卖

注意:我也尝试过使用setInterval自制倒计时器,但问题没有消失

我正在寻求此问题的帮助,并愿意补偿他们的时间和努力与我直接解决它的人。任何帮助将不胜感激。

2uluyalo

2uluyalo1#

使用setIntervalsetTimeout意味着你要受浏览器的摆布。如果其他进程正在运行,浏览器通常会减慢这些进程的执行速度,并在完成后返回到该进程,或者如果你切换到另一个选项卡,浏览器会有目的地降低滴答频率。你所需要的准确度并不容易达到。
首先,我建议先得到它结束的时间,然后找出当时和现在的差,然后从这个值开始以1s为增量倒计时,这会加剧这个问题。如果每个“tick”都偏离了哪怕是很小的量,这将累积成一个更大的错误。这可能是库默认的做法。也可能是你制作自己的计时器时所做的。但我得亲眼看看才能确定。
相反,您需要存储从套接字传递过来的结束时间(或者像下面这样将其保存在作用域中),并在每次“tick”时计算出当时和现在的时间差。
您可以通过在受控模式下使用react-countdown并在父级中执行此逻辑来完成此操作。
我在这里创建了一个函数,它可以从套接字接收时间,或者从套接字调用,它是伪代码。

const timer = useRef(null) 
const [timeLeft, setTimeLeft] = useState(null) // In seconds

const handleSocketReceived = (({endTime}) => {
    timer.current = setInterval(() => {
        const newTimeLeft = endTime - Date.now() // Pseudo code, depends on what end time is, but basically, work out the diff
        setTimeLeft(newTimeLeft)
    }, 100) // Smaller period means more regular correction

}, [])

// ...

useEffect(() => {
   return () => clearInterval(timer.current)
}, [])

// ...

 <Countdown date={timeLeft} controlled={true} />

相关问题