Коротка відповідь
juniorsetTimeout і setInterval – це API для відкладеного виконання коду. setTimeout виконує функцію один раз після заданої затримки, а setInterval – повторює її кожні N мілісекунд.
Повне пояснення
JS Core
-
Суть і призначення – обидва методи належать глобальному об’єкту
window(в браузері) абоglobal(Node.js). Вони дозволяють відкладати виконання коду, що корисно для таймерів, анімацій, повторних запитів і розкладки задач. -
Ключові принципи –
setTimeout(callback, delay)повертає ідентифікатор таймера.setInterval(callback, delay)повертає ідентифікатор інтервалу.- Обидва викликають
callbackу event loop після завершення поточного стеку. - Якщо
delay <= 0, виклик відбудеться після поточного циклу.
-
Як це працює –
- При виклику
setTimeoutстворюється запис у черзі таймерів. - Коли
delayмине, callback ставиться у чергу виконання. - Для
setIntervalпісля кожного виклику callback записується знову, доки не будеclearInterval.
- При виклику
-
Практика –
const id = setTimeout(() => console.log('one shot'), 1000); clearTimeout(id); // скасовує, якщо требаconst interval = setInterval(() => console.log('tick'), 500); // після 5s setTimeout(() => clearInterval(interval), 5000); -
Тестування –
- Використовувати
jest.useFakeTimers().
jest.useFakeTimers(); const fn = jest.fn(); setTimeout(fn, 100); jest.advanceTimersByTime(99); expect(fn).not.toBeCalled(); jest.advanceTimersByTime(1); expect(fn).toBeCalled(); - Використовувати
-
Дизайн і моделі даних – не застосовуємо.
-
Продуктивність –
- Внутрішня реалізація залежить від V8/Node.
setIntervalможе «залипнути», якщо callback триває довше, ніж delay.
-
Безпека –
- Неправильне використання може призвести до утримання пам’яті через незакриті таймери.
-
Контекст у JS Core –
- У браузері доступно через
window. - У Node.js – через глобальний об’єкт.
- У браузері доступно через
-
Edge cases і типові помилки –
- Симптом: callback не виконується. Причина:
clearTimeout/clearIntervalпередався, або функція не була оголошена. Рішення: перевірити ID. - Симптом: callback виконується частіше, ніж очікувалося. Причина:
setIntervalз коротким delay і довгим callback. Рішення: використати рекурсивнийsetTimeout. - Симптом: таймер «залип» після перезапуску. Причина:
clearIntervalне викликано. Рішення: гарантувати очищення. - Симптом:
delay> 2^31-1. Причина: обмеження JavaScript Number. Рішення: розбити на декілька таймерів. - Симптом: callback виконується після
window.close(). Причина: таймер живий у фоновому процесі. Рішення: очищати вbeforeunload. - Симптом: callback отримує неправильний контекст. Причина:
thisне прив’язаний. Рішення: використовувати arrow-функцію. - Симптом: таймер не працює в Web Worker. Причина:
setTimeout/setIntervalнедоступні безself. Рішення: використатиpostMessage. - Симптом: таймер не працює в Node.js без
setImmediate. Причина: event loop blocked. Рішення: розбити на малі частини.
- Оптимізація і best practices –
- Використовувати
setTimeoutзамістьsetInterval, коли потрібна однакова затримка між викликами. - Завжди очищати таймери у
useEffect/componentWillUnmount. - Не передавати великі об’єкти у callback, щоб уникнути копіювання.
- Альтернативи й порівняння –
requestAnimationFrameдля анімацій, бо синхронізується з перерисовкою.setImmediateу Node.js для негайного виконання після поточного циклу.
- Cheatsheet + follow-up питання –
- Q: Чому
setIntervalможе «залипнути»? A: Якщо callback триває довше delay, наступний виклик відкладений. - Q: Як скасувати таймер? A:
clearTimeout(id)абоclearInterval(id). - Q: Чи можна використовувати
setTimeoutу Web Worker? A: Так, черезself.setTimeout. - Q: Що відбувається при
delay = 0? A: Callback ставиться у чергу після поточного стеку. - Q: Як тестувати таймери в Jest? A:
jest.useFakeTimers()іjest.advanceTimersByTime.
- Діагностика –
- Симптом: callback не виконується → Перевірити ID, чи не очищено.
- Симптом: callback виконується занадто часто → Перевірити delay і тривалість callback.
- Симптом: пам’ять не звільняється → Перевірити, чи є незакриті таймери після компоненту.