首页 > 解决方案 > 将 setTimeout 与 Web Worker 一起使用时 React Hooks 延迟

问题描述

我有一个应用程序可以计算全天 2 个时间点之间的多个差异。我使用倒数计时器来显示这 2 点之间的差异。每当倒计时达到 00.00.00 时,应用程序就会在 2 个时间点之间开始下一次计算的倒计时。

所以我需要一个持续运行的倒数计时器,即使选项卡处于非活动状态。我发现当当前选项卡处于非活动状态时,setTimeout 会有一个小的延迟

这就是我到目前为止所拥有的。我已经实现了 WebWorker,但是每当我切换标签时似乎仍然存在延迟。我每秒都在记录计时器,因此我通过在单独的窗口中打开控制台并切换选项卡来对其进行测试。

这是我到目前为止所拥有的

import worker    from './worker.js';
import WebWorker from './WebWorker';
const useSetInterval = ({ prayerTime }) => {
    // SET THE STATE OF SECONDS, MINUTES AND HOURS
    const [seconds, setSeconds] = useState(60 - Number(moment().format('ss')));
    const [minutes, setMinutes] = useState(prayerTime.minutes);
    const [hours, setHours]     = useState(prayerTime.hours);

    useEffect(() => {
        const w = new WebWorker(worker);
        w.postMessage({ seconds, minutes, hours }); 

        w.addEventListener('message', e => {
            const { newSeconds, newMinutes, newHours } = e.data;
            setSeconds((newSeconds < 0) ? 59 : newSeconds);
            if (newSeconds < 0)
            {
                setMinutes((newMinutes < 0) ? 59 : newMinutes);
                if (newMinutes < 0) setHours((newHours < 0) ? "Refresh" : newHours); 
            }
        });     

        return () => w.terminate();
    }, [seconds, minutes, hours]);  

    return { seconds, minutes, hours };
};

// Webworker.js
export default class WebWorker {
    constructor(worker) {
        const code = worker.toString();
        const blob = new Blob(['('+code+')()']);
        return new Worker(URL.createObjectURL(blob));
    }
}

// worker.js
export default () => {
    self.addEventListener( "message", (e) => {
        if (!e) return;

        const { seconds, minutes, hours } = e.data;

        setTimeout(() => {
            const newSeconds = seconds - 1;
            const newMinutes = (newSeconds < 0) ? minutes - 1 : minutes;
            const newHours   = (newMinutes < 0) ? hours - 1 : hours;

            postMessage({ newSeconds, newMinutes, newHours });
        }, 1000);
    });
};

我以1000ms的速度有Settimeout,这是1秒钟,并且在选项卡不活动的情况下,我已经阅读了计时器延迟到1000ms,但仍然有延迟。任何人都可以在正确的方向上帮助我吗?

标签: javascriptreactjssettimeoutweb-workerreact-hooks

解决方案


这可能是由于 setTimeout 的不准确:JavaScript setTimeout 如此不准确的原因是什么?

当您调用 setTimeout 时,该函数将添加到事件表中,并在指定时间后执行,然后在事件循环空闲时执行。


推荐阅读