## Use setinterval 忽略的精度差問題 繼上一篇 [Use setinterval in React](https://hackmd.io/6sRDq-j1TWCTnKkhmUMYqg) 我們將 `setinterval` 封裝成 hook 去做使用。但在使用上時,我們原本的做法是通過與 `startTime` 進行比對來決定是否達到預期的延遲時間(delay),然而這種方式忽略了每次執行時產生的`微小差距`。這些差距會累積,導致最終的計時結果變得不準確,最終執行時間漸漸鈍化。 ![image](https://hackmd.io/_uploads/ByiFXdBy1e.png) 為了解決這個問題,我們新增了一個 `accumulatedTime` 變數,用來記錄每次執行後所遺漏的時間,並在下次執行時與 startTime 進行時間差的 diff。這樣的改進確保了即使 setInterval 自身的精度存在偏差,計時仍能保持準確,尤其是在長時間運行的情況下。 > 這種方式有效地提高了 setInterval 的時間精度,避免了時間鈍化,並使其在需要高精度計時的場景中表現更穩定。 ### Poo Poo Code ```javascript= import { useEffect, useRef } from 'react' export default (callback: () => void, delay: number | null): void => { const savedCallback = useRef<() => void>() const startTime = useRef<number>(0) const accumulatedTime = useRef<number>(0) useEffect(() => { savedCallback.current = callback }, [callback]) useEffect(() => { if (delay === null) return startTime.current = Date.now() - accumulatedTime.current const tick = (): void => { const now = Date.now() const elapsed = now - startTime.current if (elapsed >= delay && savedCallback.current !== undefined) { savedCallback.current() startTime.current += delay accumulatedTime.current = elapsed - delay } } const id = setInterval(tick, Math.min(10, delay)) return (): void => clearInterval(id) }, [delay]) } ```