Чтобы запустить функцию через какой-то промежуток времени, существует конструкция, которая называется
setTimeout.
Синтаксис такой:
Код
const timerId = setTimeout();
Первым аргументом принимается та функция, которая должна быть запущена через определённый промежуток времени, в виде её объявления или названия, не вызов функции.
Код
const timerId = setTimeout(function() {
console.log('Hello');
});
Вторым аргументом указывается время в миллисекундах, через которое должен произойти вызов этой функции.
Код
const timerId = setTimeout(function() {
console.log('Hello');
}, 2000);
Можно также использовать третий аргумент, который будет передаваться вовнутрь функции, например:
Код
const timerId = setTimeout(function(text) {
console.log(text);
}, 2000, 'Hello'); // Hello
Как вариант, можно в качестве аргумента передавать функцию.
Например, создадим функцию
logger и передадим её в качестве первого аргумента:
Код
const timerId = setTimeout(logger, 2000);
function logger() {
console.log('Hello');
}
Спустя две секунды функция
logger вызовется и в консоли появится сообщение
"Hello" setTimeout не обязательно было сохранять в переменную
timerId, он точно также бы отработал, но, когда мы таким образом записываем, мы сохраняем в переменной
числовой идентификатор таймера, что нам потребуется впоследствии, чтобы отключить этот
setTimeout Очистить
setTimeout можно с помощью команды
clearInterval():
Код
const timerId = setTimeout(logger, 2000);
clearInterval(timerId);
Реализуем функционал,в котором команда очистки интервала будет выполняться после какого-то действия, например, после клика на кнопку.
Есть такая структура кода:
Код
<button class="btn">Animation</button>
<div class="wrapper">
<div class="box"></div>
</div>
И минимальный набор стилей:
Код
.box {
position: absolute;
width: 100px;
height: 100px;
background-color: blue;
}
.wrapper {
position: relative;
width: 400px;
height: 400px;
border: 3px solid red;
}
button {
margin-bottom: 10px;
margin-top: 10px;
width: 100px;
height: 40px;
background-color: yellow;
border: none;
}
Получим кнопку с классом
.btn Код
const btn = document.querySelector('.btn');
И добавляем для неё обработчик события, суть его - после клика на кнопку будет запускаться таймер:
Код
btn.addEventListener('click', () => {
const timerId = setTimeout(logger, 2000);
})
function logger () {
console.log('Text');
}
Если нам нужно, чтобы скрипт повторялся не один раз, а каждый раз через определённое количество времени, то для этого используется
setInterval() Код
btn.addEventListener('click', () => {
const timerId = setInterval(logger, 2000);
})
Сейчас у нас такой код скрипта:
Код
btn.addEventListener('click', () => {
const timerId = setInterval(logger, 2000);
})
clearInterval(timerId);
function logger () {
console.log('Text');
}
И сброс таймера в нём не работает, потому что переменная
timerId объявлена внутри функции, она локальная и не видна снаружи.
Вариант решения данной проблемы это создать переменную
timerId глобально, а внутри функции уже присвоить ей значение:
Код
let timerId;
btn.addEventListener('click', () => {
timerId = setInterval(logger, 2000);
});
Но и теперь сброс таймера не будет работать, потому что он идёт в потоке синхронного кода, то есть, за счёт того, что функция
setInterval бесконечно срабатывает и срабатывает через каждые 2 секунды, код до
clearInterval() попросту не доходит.
Поэтому можно сделать так: внутри функции
logger мы можем отслеживать, сколько раз повторился
setInterval.
Для этого назначим переменную-счётчик
i с первоначальным нулевым значением и каждый раз после срабатывания таймера будем прибавлять ей единицу.
Как только значение
i достигнет, к примеру, трёх, запускается очистка таймера.
Код
const btn = document.querySelector('.btn');
let timerId;
let i = 0;
btn.addEventListener('click', () => {
timerId = setInterval(logger, 2000);
})
function logger() {
if (i === 3) {
clearInterval(timerId);
}
console.log('Text');
i++;
}
Рекурсивный setTimeout. Чем он лучше setInterval?
Всё дело в том, что когда таймер
setInterval работает, он не учитывает, как долго будет работать код функции внутри него, ему всё равно, сколько по времени будет работать функция
logger.
И может получиться так, что, к примеру, таймер установлен на 0.5 секунды, а код функции выполняется 3 секунды. Как будет в этом случае работать таймер?
Он просто не будет ждать на следующем повторении эти полсекунды, поскольку будет считать, что они уже прошли во время выполнения функции и вновь вызовет выполнение функции
logger Для решения такой проблемы обычно используют
рекурсивный setTimeOut, разберём на примере:
Код
let id = setTimeout(function log() {
console.log('Hello'); // не важно сколько по времени идет этот код
id = setTimeout(log, 500); // запустится через полсекунды после выполнения кода выше
}, 500);
Что происходит теперь?
Запускается основной таймер, проходит полсекунды, запускается код функции
log, в консоль выводится сообщение
'Hello'.
Затем вступает в действие таймер внутри функции, но он будет строго дожидаться пока код до него полностью выполнится, а потом подождёт полсекунды, прежде чем запустить функцию
log снова. И сколько бы по времени не продолжался код до него, этот таймер будет запускаться строго после выполнения этого кода и затем через полсекунды.
Практика: построение анимации
Цель: при нажатии на кнопку, синий квадрат плавно по диагонали перемещается в нижний правый угол.
Начинаем писать функцию
myAnimation. Внутри функции получим элемент, с которым будем взаимодействовать (синий квадрат).
Там же создадим переменную, в которую запишем нулевое значение стартовой позиции квадрата.
Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
};
Дальше нам понадобится функция, которая будет запускаться через определённый промежуток времени. В этой функции нам нужно прописать условие, определяющее в какой момент наша анимация должна закончиться.
Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
function frame() {
if (pos == 300) {
clearInterval()
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
};
Чтобы сделать плавную анимацию, нам нужно запустить интервал, чтобы вызывать через определённый промежуток времени функцию
frame Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
const id = setInterval(frame, 10); // вызов функции каждые 10 миллисекунд
function frame() {
if (pos == 300) {
clearInterval(id)
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
};
Осталось в конце кода добавить обработчик события для кнопки:
Код
btn.addEventListener('click', myAnimation);
Всего комментариев: 1