Таймеры и планирование
setTimeout
Выполняет функцию один раз через указанное время:
setTimeout(() => console.log('позже'), 1000);
Возвращает ID для отмены:
const id = setTimeout(() => {}, 1000);
clearTimeout(id);
setInterval
Выполняет функцию регулярно:
const id = setInterval(() => console.log('тик'), 1000);
clearInterval(id);
Задержка не точная
setTimeout(fn, 100) — не «ровно через 100мс», а «не раньше». Задержка может быть больше из-за занятости event loop.
const start = Date.now();
setTimeout(() => console.log(Date.now() - start), 100);
// может быть 105, 110, 200...
setInterval и накопление
Если функция выполняется дольше интервала — вызовы накапливаются:
setInterval(() => {
// если это занимает 2 секунды при интервале 1 секунда —
// вызовы будут догонять
}, 1000);
Решение — setTimeout с рекурсией:
function tick() {
doWork();
setTimeout(tick, 1000);
}
tick();
Следующий вызов — через секунду после завершения текущего.
Асинхронный интервал
async function tick() {
await doWork();
setTimeout(tick, 1000);
}
tick();
Работает как setInterval, но не накапливает вызовы.
Delay через промис
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function main() {
console.log('начало');
await sleep(1000);
console.log('через секунду');
}
requestAnimationFrame
Вызывает функцию перед отрисовкой следующего кадра (обычно 60 раз в секунду):
function animate() {
// обновление позиции
element.style.transform = `translateX(${x}px)`;
x += 1;
if (x < 100) requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Синхронизируется с частотой монитора. Лучше для анимаций, чем setInterval.
Отмена анимации
let id = requestAnimationFrame(animate);
cancelAnimationFrame(id);
requestIdleCallback
Вызывает функцию, когда браузер свободен:
requestIdleCallback((deadline) => {
while (deadline.timeRemaining() > 0 && tasks.length) {
doTask(tasks.shift());
}
}, { timeout: 2000 });
Не гарантирует вызов, но и не мешает важной работе.
Микро-таймеры
queueMicrotask — задача выполнится перед следующей макрозадачей:
queueMicrotask(() => console.log('микрозадача'));
Эквивалент Promise.resolve().then(...).
Debounce
function debounce(fn, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
const search = debounce((q) => fetchResults(q), 300);
Throttle
function throttle(fn, delay) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last >= delay) {
last = now;
fn.apply(this, args);
}
};
}
Расписание в Node.js
setImmediate(() => console.log('после текущей фазы'));
process.nextTick(() => console.log('до следующей микротаски'));
Порядок: синхронный код → process.nextTick → микрозадачи → макрозадачи.
Итоги
setTimeout— один разsetInterval— регулярно, может накапливатьrequestAnimationFrame— для анимацийsleepчерез промисdebounceиthrottleдля событий- Микротаймеры для срочных задач