TGViewer
Виталий и Платформа Виталий и Платформа @web_platform · 1.81K subscribers
Post #69 450
#Лаборатория_веб_платформы

Таймер без фриза с помощью Web Worker

Если в JS запустить таймер с помощью setInterval, который срабатывает довольно часто, например, раз в 100мс, а затем уйти из таба на некоторое время, то окажется, что браузер остановит таймер на время «неактивности» таба. «Фриз» таймера в неактивном табе можно посмотреть тут https://codesandbox.io/p/sandbox/dreamy-bartik-vkkmjr.

Это не баг, а фича: с целью экономии ресурсов браузеры троттлят фоновую активность тех табов, которые сейчас не открыты.

Но как быть, если нужно, чтобы таймер в фоновом табе гарантированно работал без замедления и остановки? На помощь приходит веб воркер, который работает в браузере отдельном потоке и поэтому на его работу оптимизации основного потока не распространяются.

Вот пример таймера в отдельном файле воркера, к примеру, timerWorker.ts :



let timerId: number | null = null;

self.onmessage = (event: MessageEvent) => {
const { data } = event;

switch (data) {
case "start":
timerId = self.setInterval(() => {
self.postMessage("tick");
}, 100);
break;
case "stop":
if (timerId) {
clearInterval(timerId);
timerId = null;
}
break;
}
};


В воркере нет объекта window, но есть self, местный аналог https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/self. С основным приложением воркер общается с помощью команды postMessage. При этом из приложения также можно дёргать postMessage воркера и подписываться на событие onmessage:



function App() {
const [time, setTime] = useState<number>(0);
const workerRef = useRef<Worker | null>(null);

useEffect(() => {
workerRef.current = new Worker("/timerWorker.ts");

workerRef.current.postMessage("start");

workerRef.current.onmessage = (event) => {
if (event.data === "tick") {
setTime((prevTime) => prevTime + 1);
}
};

return () => {
workerRef.current?.postMessage("stop");
};
}, []);

return <div>{time}</div>;
}


В воркере, к сожалению, нет доступа к DOM-у, но зато доступны разные API, например, Fetch или Canvas, так что выгружать в воркер что-то тяжёлое или важное — вполне себе рабочая тема, о которой не стоит забывать.
  • 👍 8
  • ❤ 1
More from @web_platform
  1. Aug 14, 2026Мой воркфлоу с ИИшками сейчас У меня счас несколько подписок: • антропик 20$ (для разработ…
  2. Jul 13, 2026Hermes vs OpenClaw В комметах к прошлому посту @fogrew спросил, чем Hermes отличается от O…
  3. Jul 8, 2026Недавний инцидент с ДЦ сподвиг меня причесать всё на VPS с ботом-дайджестёром. Раньше было…
  4. Jul 2, 2026вчера мой ботик @web_platform_pulse_bot не прислал новости, а всё потому что кукольный теа…
  5. Jun 22, 2026btw там интересная система в репе, используются git submodules: в .gitmodules указывается…
  6. Jun 22, 20264 мая -> 20 июня, столько провисел мой pr в zed до мерджа зато теперь тема superset доступ…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →