Таймери
Таймер - це затримка виконання функції на вказаний час.
JavaScript підтримує роботу з двома типами таймерів - одноразовим setTimeout() та багаторазовим setInterval().
Кожна з цих функцій приймає в себе щонайменше 2 аргумента: функцію, яка має виконатися, і час в мілісекундах:
setTimeout(function(){
console.log('hello!');
}, 5000);
let i = 5;
setInterval(fun, 1000);
function fun(){ console.log(i++); }
Якщо у функцію треба передати аргументи - вони прописуються в кінець, після часу затримки:
setTimeout(function(a, b, c){
console.log(a + b + c);
}, 3000, 5, 10, 20);
setInterval(fun, 1000, 'hello');
function fun(k){ console.log(k); }
Таймер можна зупинити, вимкнути. Кожна з вищевказаних функцій повертає ідентифікатор таймера (число), зупинити можна двома функціями:
var a = setTimeout(fun, 5000);
var b = setInterval(fun, 8000);
button.onclick = function(){
clearTimeout(a);
clearInterval(b);
}
Функції таймерів є асинхронними, тобто - вони можуть виконуватися паралельно з виконанням іншого коду. Про це треба пам'ятати і бути обережним.
Розглянемо приклади:
// що відобразить alert?
let x = 5;
setTimeout(function(){ alert(x); }, 100);
x = 10;
// хочемо вивести в консоль текст перших 5-и абзаців:
let p = document.querySelectorAll('p');
for (var i = 0; i < 5; i++){
setTimeout(function(){
console.log(p[i].innerText);
}, (i + 1) * 1000);
}
(Наступна інформація була актуальна у 2015-2017 роках, наразі є застарілою через повсюдне використання оператора let).
Ця задача популярна на співбесідах:
"Що буде виведено в консоль?"
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log('Index: ' + i + ', element: ' + arr[i]);
}, 3000);
}
Останній варіант має декілька варіантів правильного розв'язку:
// використаємо let замість var (подробиці тут):
let p = document.querySelectorAll('p');
for (let i = 0; i < 5; i++){
setTimeout(function(){ console.log(p[i].innerText); }, (i + 1) * 1000);
}
// передамо у функцію потрібний абзац у якості аргумента:
var p = document.querySelectorAll('p');
for (var i = 0; i < 5; i++){
setTimeout(function(e){ console.log(e.innerText); }, (i + 1) * 1000, p[i]);
}
// елемент можна передати в функцію не як аргумент, а як батька:
...
setTimeout(function(){ console.log(this.innerText); }.bind(p[i]), ...);
...
// можна використати метод forEach, з ним також код буде працювати вірно. Спробуйте самі.
Завдання
- Опишіть порядок виконання команд у наступних алгоритмах:
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
setTimeout((function(i) {
return function() { console.log(i, arr[i]); }
})(i), 3000);
}
for (var i = 0; i < arr.length; i++) {
(function(i){
setTimeout(function() { console.log(i, arr[i]); }, 3000);
})(i);
} -
Домашнє завдання
- Через 5 секунд після відкриття сторінки вивести на екран повідомлення "5 seconds!".
- Зробити таймер, що починає відлік з 3:30, рахує посекундно у зворотньому напрямку і після досягнення значення 0:00 замість цифр видає текст "BOOM!!!" (прим.: тероризм - це погано).
-
Виправте код, щоб у консолі видавало цифри 1, 2, 3, 4, 5:
for (var i = 0; i < 5; i++) {Переробіть цей код так, щоб у ньому була рекурсія.
setTimeout(function() {
console.log(i + 1);
}, i * 1000);
}
Спробуйте застосувати setInterval. -
Зробити годинник, що відображає в браузері поточні дату та час - день, місяць, рік, день тижня, години, хвилини, секунди. Синхронізацію проводити 1 раз на 5 хвилин.
Рекомендації до виконання: раціонально створити масив змінних [Y, M, D, d, h, m, s] та 3 функції: синхронізацію з годинником комп’ютера; функцію, що повертає оформлену строку з датою та часом та функцію, яка буде робити розрахунки додавання секунди та перевірки хвилин, годин і т.п. на перевищення допустимих значень. В таймері setInterval потрібно зробити додавання секунди, виведення строки та 1 раз на 300 циклів проводити синхронізацію.
Зауваження. Можна щосекунди брати системний час та виводити його вбудованими функціями, типу .toString(), .toLocaleString() і т.п., але перед нами стоїть задача навчитися оперувати складовими дати та часу.