Skip to main content
Практика завдань

Як працюють таймери та планування в Node.js?

Таймери в Node.js

Node.js надає кілька функцій таймерів для планування виконання коду. Вони інтегруються з циклом подій і виконуються на різних етапах.


Функції таймерів

setTimeout — Виконати один раз після затримки

js
const timer = setTimeout(() => { console.log('Виконано через 2 секунди'); }, 2000); // Скасувати за необхідності clearTimeout(timer);

setInterval — Виконувати повторно

js
let count = 0; const interval = setInterval(() => { console.log(`Тік ${++count}`); if (count >= 5) clearInterval(interval); }, 1000);

setImmediate — Виконати на наступній ітерації циклу подій

js
setImmediate(() => { console.log('Виконується на етапі перевірки циклу подій'); });

process.nextTick — Виконати перед будь-яким I/O

js
process.nextTick(() => { console.log('Виконується перед будь-яким I/O в мікрозавданні'); });

Порядок виконання

js
console.log('1 - синхронний'); setTimeout(() => console.log('2 - setTimeout'), 0); setImmediate(() => console.log('3 - setImmediate')); process.nextTick(() => console.log('4 - nextTick')); Promise.resolve().then(() => console.log('5 - Promise')); console.log('6 - синхронний'); // Вихід: // 1 - синхронний // 6 - синхронний // 4 - nextTick // 5 - Promise // 2 - setTimeout (або 3 — порядок між setTimeout(0) і setImmediate // 3 - setImmediate // є недетермінованим поза циклом I/O)

Точність таймерів

Таймери в Node.js є не точними. Вони гарантують мінімальну затримку, а не точну:

js
const start = Date.now(); setTimeout(() => { console.log(`Фактична затримка: ${Date.now() - start}ms`); // Буде >= 100ms, часто 101-105ms }, 100);

Розширене: AbortController з таймерами

js
const { setTimeout: sleep } = require('timers/promises'); async function fetchWithTimeout(url, ms) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), ms); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeout); return response; } catch (err) { if (err.name === 'AbortError') { throw new Error(`Запит перевищив час очікування після ${ms}ms`); } throw err; } }

Промісовані таймери (Node.js 16+)

js
const { setTimeout, setInterval, setImmediate } = require('timers/promises'); // Очікування затримки await setTimeout(1000); console.log('Пройшла 1 секунда'); // Ітерація за інтервалом const interval = setInterval(1000); for await (const _ of interval) { console.log('тік'); break; // зупинити після першого тіку }

Загальні патерни

Дебаунс

js
function debounce(fn, delay) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; }

Повтор з експоненційною затримкою

js
async function retryWithBackoff(fn, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await fn(); } catch (err) { if (i === maxRetries - 1) throw err; const delay = Math.pow(2, i) * 1000; // 1с, 2с, 4с await new Promise(resolve => setTimeout(resolve, delay)); } } }

Підсумкова таблиця

ФункціяКоли виконуєтьсяЕтап
process.nextTick()Після поточної операції, перед I/OМікрозавдання
Promise.then()Після nextTickМікрозавдання
setTimeout(fn, 0)Мінімальна затримка після поточного циклуТаймери
setImmediate()Наступна ітерація, етап перевіркиПеревірка
setInterval()Повторно через інтервалТаймери

Найкраща практика: Використовуйте setImmediate() для розподілу роботи, що вимагає великих обчислень. Використовуйте setTimeout() для фактичних затримок. Віддавайте перевагу timers/promises для async/await. Уникайте setInterval у серверному коді — використовуйте бібліотеки cron або черги повідомлень замість цього.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань