Пошук уроків, статей та іншого контенту
Навчитеся планувати виконання функцій через setTimeout і setInterval та правильно зупиняти повторювані таймери.
Таймери дають змогу виконати функцію не одразу, а через певний час або регулярно через однакові проміжки часу.
У JavaScript є два основні таймери:
setTimeout — виконує функцію один раз після затримки;
setInterval — виконує функцію повторно через заданий інтервал.
Затримка вказується в мілісекундах:
1000 мс = 1 секунда;
5000 мс = 5 секунд;
500 мс = пів секунди.
Таймер не гарантує виконання функції точно в зазначений момент. Він лише ставить функцію в чергу на виконання після завершення затримки.
setTimeoutСинтаксис:
setTimeout(function, delay);function — функція, яку потрібно виконати;
delay — затримка в мілісекундах.
setTimeout(() => {
console.log("Повідомлення з'явилося через 2 секунди");
}, 2000);Спочатку JavaScript зареєструє таймер, а потім продовжить виконувати наступні інструкції:
console.log("Початок");
setTimeout(() => {
console.log("Таймер завершився");
}, 1000);
console.log("Кінець");Результат:
Початок
Кінець
Таймер завершивсяНавіть якщо затримка дорівнює 0, функція з setTimeout не виконається негайно:
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
console.log("3");Результат:
1
3
2Функція буде виконана після завершення поточного коду.
setTimeoutНайзручніше передавати аргументи через стрілкову функцію:
const userName = "Олена";
setTimeout(() => {
console.log(`Привіт, ${userName}!`);
}, 1000);Можна також передати аргументи після затримки:
function greet(name) {
console.log(`Привіт, ${name}!`);
}
setTimeout(greet, 1000, "Олена");Не потрібно викликати функцію одразу:
// Правильно
setTimeout(greet, 1000);
// Неправильно: greet виконається одразу,
// а результат її виклику буде передано в setTimeout
setTimeout(greet(), 1000);setTimeoutsetTimeout повертає ідентифікатор таймера. Його можна використати для скасування запланованого виконання:
const timerId = setTimeout(() => {
console.log("Цей текст не з'явиться");
}, 3000);
clearTimeout(timerId);Після виклику clearTimeout функція таймера не буде виконана.
Це корисно, наприклад, коли користувач почав вводити текст, але потім очистив поле або перейшов на іншу сторінку.
setIntervalsetInterval запускає функцію через однакові проміжки часу:
const intervalId = setInterval(() => {
console.log("Цей текст з'являється кожну секунду");
}, 1000);На відміну від setTimeout, setInterval продовжує працювати, доки його не зупинити.
setIntervalДля зупинки інтервалу використовується clearInterval:
const intervalId = setInterval(() => {
console.log("Повторення");
}, 1000);
setTimeout(() => {
clearInterval(intervalId);
console.log("Інтервал зупинено");
}, 5000);У цьому прикладі повідомлення виводиться приблизно чотири або п’ять разів, після чого інтервал зупиняється.
Зберігайте ідентифікатор інтервалу в змінній:
let intervalId = setInterval(() => {
console.log("Робота інтервалу");
}, 1000);
// Пізніше інтервал можна зупинити
clearInterval(intervalId);Наступний приклад запускає відлік від 5 до 0, а потім зупиняє інтервал:
let secondsLeft = 5;
const intervalId = setInterval(() => {
console.log(`Залишилося секунд: ${secondsLeft}`);
secondsLeft -= 1;
if (secondsLeft < 0) {
clearInterval(intervalId);
console.log("Відлік завершено");
}
}, 1000);Можливий результат:
Залишилося секунд: 5
Залишилося секунд: 4
Залишилося секунд: 3
Залишилося секунд: 2
Залишилося секунд: 1
Залишилося секунд: 0
Відлік завершеноОскільки перевірка відбувається після виведення значення, повідомлення з 0 також буде показано.
setTimeout замість setIntervalДля послідовних операцій часто краще використовувати рекурсивний setTimeout:
let count = 0;
function printMessage() {
count += 1;
console.log(`Повідомлення №${count}`);
if (count < 5) {
setTimeout(printMessage, 1000);
}
}
printMessage();У цьому випадку наступний таймер створюється лише після завершення поточного виклику функції.
Такий підхід може бути зручнішим, якщо робота між викликами має різну тривалість. Наприклад, якщо функція виконує запит до сервера, новий запуск можна запланувати тільки після завершення попереднього.
Цей приклад можна запустити в Node.js або в консолі браузера:
let seconds = 0;
console.log("Таймер запущено");
const intervalId = setInterval(() => {
seconds += 1;
console.log(`Минуло секунд: ${seconds}`);
if (seconds === 5) {
clearInterval(intervalId);
console.log("Таймер зупинено");
}
}, 1000);У браузері результат буде видно в консолі розробника. У Node.js файл можна запустити командою:
node timer.jsТаймери є асинхронними операціями. JavaScript не зупиняє виконання всієї програми, поки очікується затримка.
console.log("До таймера");
setTimeout(() => {
console.log("Всередині таймера");
}, 2000);
console.log("Після таймера");Порядок виконання:
виводиться "До таймера";
створюється таймер;
виводиться "Після таймера";
приблизно через 2 секунди виводиться "Всередині таймера".
Якщо основний код виконується довго, таймер також може спрацювати пізніше, ніж зазначено:
setTimeout(() => {
console.log("Таймер");
}, 1000);
// Довга синхронна операція блокує виконання JavaScript
for (let i = 0; i < 1_000_000_000; i += 1) {
// Навмисно порожній цикл
}
console.log("Цикл завершено");Затримка 1000 означає «не раніше ніж через 1000 мс», а не «рівно через 1000 мс».
// Правильно
setTimeout(() => {
console.log("Готово");
}, 1000);
// Неправильно
setTimeout(console.log("Готово"), 1000);У неправильному варіанті console.log виконається одразу.
setInterval(() => {
console.log("Інтервал продовжується без кінця");
}, 1000);Якщо інтервал більше не потрібен, його потрібно зупинити за допомогою clearInterval.
setInterval(() => {
console.log("Повторення");
}, 1000);
// Немає доступного ідентифікатора,
// тому зупинити саме цей інтервал складноКраще одразу зберегти результат:
const intervalId = setInterval(() => {
console.log("Повторення");
}, 1000);
clearInterval(intervalId);Якщо функція викликається кілька разів і щоразу створює новий інтервал, усі інтервали працюватимуть паралельно:
function startTimer() {
setInterval(() => {
console.log("Тік");
}, 1000);
}
startTimer();
startTimer();Тепер повідомлення з’являтиметься двічі на секунду. Щоб уникнути цього, перевіряйте, чи таймер уже запущений, або зупиняйте попередній інтервал перед створенням нового.
setInterval(..., 1000) не є точним годинником. На момент виконання можуть впливати:
завантаження процесора;
інші синхронні операції;
призупинення вкладки браузера;
черга інших завдань.
Для простих повідомлень, відліків і періодичних дій цього зазвичай достатньо. Для точного вимірювання часу краще порівнювати реальний час за допомогою Date.now() або іншого відповідного механізму.
Створіть таймер, який:
виводить "Завантаження..." через 2 секунди;
кожну секунду виводить номер секунди;
після п’яти секунд зупиняє повторення;
виводить "Готово" після зупинки.
Один із можливих варіантів:
let seconds = 0;
const intervalId = setInterval(() => {
seconds += 1;
console.log(`Минає секунда: ${seconds}`);
if (seconds === 5) {
clearInterval(intervalId);
console.log("Готово");
}
}, 1000);
setTimeout(() => {
console.log("Завантаження...");
}, 2000);setTimeout виконує функцію один раз після затримки.
setInterval повторює виконання функції через заданий проміжок часу.
Затримка задається в мілісекундах.
clearTimeout скасовує таймер, створений через setTimeout.
clearInterval зупиняє таймер, створений через setInterval.
Ідентифікатор таймера потрібно зберігати, якщо його планується скасувати.
Таймери не блокують виконання JavaScript.
Зазначена затримка є мінімальною, а не гарантією точного часу виконання.
Для послідовних операцій іноді краще використовувати повторний setTimeout, а не setInterval.