Планирование вызова функции: setTimeout

JavaScript простым языком

Generic badge

Представь, у тебя есть задача вывести приветственное сообщение пользователю через 5 секунд после того, как он перешел на страницу. Как это организовать средствами JavaScript?

В этом вопросе нам поможет метод объекта windowsetTimeout(). Данный метод запускает через указанное в аргументах время, указанную в аргументах функцию. Пример использования:

// 1-й вариант использования
window.setTimeout(func, delay);

// 2-й вариант использования
setTimeout(func, delay);

Как видишь, данный метод объекта window можно вызывать и как обычную функцию (2-й вариант использования). Я, кстати, рекомендую использовать именно 2-й вариант, так как он чаще всего встречается и используется.

В качестве аргументов мы передаем func и delay, где func– это функция, либо ссылка на функцию, которую должен запустить setTimeout после того, как пройдет время delay (указывается в миллисекундах). Кстати, такие функции, которые передаются в другие функции в качестве аргументов – называются callback-функциями или функциями обратного вызова.

Теперь вернемся к нашей задаче поставленной в начале урока и поприветствуем нашего пользователя:

function hello() {
   alert('Привет!');
}

setTimeout(hello, 5000);

Функция hello, в данном примере, является callback-функцией, которую нужно запустить после того как пройдет 5000 миллисекунд (5 сек). В данном примере, в качестве первого аргумента, мы передали ссылку на функцию hello. Ссылка на функцию – это ее имя, а не вызов. Т.е.:

hello; // - это ссылка на функцию
hello(); // - это вызов функции

В качестве аргумента мы должны передавать либо ссылку на функцию, либо описание функции (смотри ниже), но никогда не должны передавать вызов функции!

Есть и другие варианты передачи callback-функции, которые делают ровно тоже самое.

В качестве первого аргумента, мы можем передать анонимную (безымянную) функцию:

setTimeout(function() { alert('Привет!'); }, 5000);

Так же можем передать анонимную стрелочную функцию:

setTimeout(() => alert('Привет!'), 5000);

Небольшое отступление: использование анонимных функций позволяет не описывать callback-функцию в глобальной области видимости, т.е. анонимная функция, описание которой ты передашь в качестве первого аргумента будет доступна только для setTimeout, и не доступна ни для кого извне, что, иногда, является лучшим решением.

Продолжим.

Самое интересное, что мы можем передать строку, вместо функции и она выполнится:

setTimeout(`alert('Привет!')`, 5000);

Все варианты выполняют одну и ту же задачу, но, последний вариант с передачей строки не рекомендуется использовать так как это и стилистически некрасиво и в плане безопасности – это плохой вариант.

setTimeout(`alert('Привет!')`, 5000);

Стоит запомнить, что такой вариант может встретиться в чужом коде, но в своём такой писать не стоит.

Последнее что хотелось бы отметить, так это то, что метод setTimeout нужно удалять, чтобы не произошло утечки памяти. Делается это достаточно просто.

setTimeout на самом деле еще и возвращает данные, а именно, он возвращает свой идентификатор. Стоит понимать, что у каждого setTimeout этот идентификатор индивидуальный, свой. Чтобы не произошло утечки памяти, нужно удалять setTimeout после выполнения. Сделать этом можно с помощью clearTimeout(id), где в качестве аргумента нужно передать идентификатор вашего setTimeout.

Для начала давай сохраним идентификатор нашего setTimeout в константе timerId:

function hello() {
   alert('Привет');
}

const timerId = setTimeout(hello, 5000); 

Удалить setTimeout из памяти нам нужно после выполнения приветствия, поэтому добавим clearInterval в функцию hello, после вывода приветствия:

function hello() {
   alert('Привет');
   clearInterval(timerId);
}

const timerId = setTimeout(hello, 5000); 

Всё, теперь после выполнения приветствия setTimeout будет удален из памяти.

Еще один небольшой пример:

function hello() {
   alert('Привет');
}

const timerId = setTimeout(hello, 5000);
clearInterval(timerId);

В данном случае setTimeout не будет выполнен совсем, потому что мы вызвали cleatInterval сразу же после объявления setTimeout, данным действием мы как бы отменили (удалили)setTimeout.

Last updated