Примеры использования функции setTimeout()
JavaScript

Примеры использования функции setTimeout()

Оригинал: jQuery setTimeout() Function Examples, James Hibbard

Функция setTimeout является нативной функцией JavaScript (хотя может использоваться и в какой-либо библиотеке, например jQuery, как мы увидим позже), которая вызывает функцию или выполняет некоторый код после указанной задержки (в миллисекундах). Это может быть полезно, если, например, вы хотите отобразить всплывающее окно после того, как посетитель пробыл на странице в течение определенного времени, или вы хотите добавить небольшую задержку перед обработчиком потери курсора (в случае, если пользователь случайно убрал курсор мыши).

Базовый пример использования setTimeout

Чтобы посмотреть принцип работы, отратите внимание на демо ниже, которое открывает всплывающее окно через две секунды после того, как нажата кнопка.

See the Pen Set Timout modal by SitePoint (@SitePoint) on CodePen.

Синтаксис

Согласно документации MDN , функция setTimeout имеет следующий синтаксис:


var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]);
var timeoutID = window.setTimeout(code, [delay]);

где:

  • timeoutID — числовой идентификатор, который может использоваться функцией clearTimeout() для отмены таймера.
  • func — функция, которая будет выполнена.
  • code (альтернативный синтаксис) — блок кода, который будет выполнен.
  • delay — задержка в миллисекундах, по истечении которой будет выполнена функция. По умолчанию равна 0.

setTimeout и window.setTimeout

Вы заметили, что в систаксисе выше используется window.setTimeout. Почему?

Ну, setTimeout и window.setTimeout — это по сути одно и то же, разница лишь в том, что во втором случае мы ссылаемся на setTimeout как на свойство глобального объекта window.

На мой взгляд, это лишь добавляет сложности, небольшое преимущество — если вы определите где-то альтернативный метод setTimeout, который будет расположен раньше в цепочке областей видимости, у вас будут большие проблемы.

В примерах я буду опускать window, какой синтаксис использовать — решать вам.

Примеры использования

Функция setTimeout принимает ссылку на функцию в качестве первого аргумента.

Это может быть имя функции:


function explode(){
  alert("Boom!");
}
setTimeout(explode, 2000);

Переменная, ссылающаяся на функцию:


var explode = function(){
  alert("Boom!");
};
setTimeout(explode, 2000);

Анонимная функция:


setTimeout(function(){
  alert("Boom!");
}, 2000);

Также в setTimeout можно передать строку кода:


setTimeout("alert('Boom!');", 2000);

Однако это не рекомендуется по следующим причинам:

  • Такой способ затрудняет чтение (а также сопровождение и/или отладку).
  • Внутри используется eval(), что является небезопасным.
  • Этот способ медленнее остальных, т.к. вызывает интерпретатор JS.

На StackOverflow можно почитать об этом подробнее.

Передача параметров в setTimeout

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

В примере ниже мы выбираем случайное приветствие из массива greetings и передаем его в качестве параметра функции greet.


function greet(greeting){
    console.log(greeting);
}
 
function getRandom(arr){
    return arr[Math.floor(Math.random()*arr.length)];
}
 
var greetings = ["Hello", "Bonjour", "Guten Tag"],
    randomGreeting = getRandom(greetings);
 
setTimeout(function(){
    greet(randomGreeting);
}, 1000);

Альтернативный способ

Как видно из синтаксиса в начале статье, есть второй способ передачи параметров в функцию обратного вызова, выполняемую setTimeout. Он заключается в передаче параметров непосредственно в функцию setTimeout после задержки.


setTimeout(greet, 1000, randomGreeting);

К сожалению, этот метод не работает в IE 9 и ниже, значением всех параметров в этих бразуерах будет undefined. Существует полифилл, который доступен на MDN .

Проблема «this»

Код, выполняемый в setTimeout, выполнятся в отдельном контексте выполнения. Это становится проблемой, когда важно сохранить значение переменной this.


var person = {
    firstName: "Jim",
    introduce: function(){
        console.log("Hi, I'm " + this.firstName);
    }
};
 
person.introduce();
// Outputs: Hi, I'm Jim
 
setTimeout(person.introduce, 50);
// Outputs: Hi, I'm undefined

Причина ошибки в примере выше заключается в том, что в функции setTimeout значением this является глобальный объект window (который не имеет свойства firstName).

Для решения этой проблемы существуют различные способы.

Явное задание значения this

Для явного задания значения this можно использовать функцию bind().


setTimeout(person.introduce.bind(person), 50);

Обратите внимание: функция bind() является частью стандарта ECMAScript 5, она не поддерживается старыми браузерами.

Использование библиотеки

Многие библиотеки имеют встроенную функцию для решения этой проблемы. Например, jQuery имеет метод jQuery.proxy(). Он принимает функцию и возвращает новую с установленным контекстом выполнения. В нашем случае:


setTimeout($.proxy(person.introduce, person), 50);

Отмена таймера

Функция setTimeout возвращает числовой id, который может использоваться функцией clearTimeout() для отмены таймера.


var timer = setTimeout(myFunction, 3000);
clearTimeout(timer);

Посмотрите пример ниже. Если нажать кнопку «Start countdown», начнется обратный отсчет. Если он завершится, котята исчезнут. Если нажать кнопку «Stop countdown», обратный отсчет будет отменен.

See the Pen SetTimeout Kittens by SitePoint (@SitePoint) on CodePen.

Подводя итог

Одна из потенциальных ловушек, которую нужно иметь в виду, заключается в том, что setTimeout является асинхронным, она ставит функцию в очередь и запускает, когда текущий стек вызовов закончит выполнение. Все это выполняется в одном потоке (в связи с однопоточной природой JavaScript).


console.log(1);
setTimeout(function(){
  console.log(2);
  }, 0);
console.log(3);
 
// Outputs: 1, 3, 2

Существует также некоторая путаница при использовании нативной функции setTimeout и метода jQuery delay .

Метод delay добавляет определенную задержку между вызовами методов, нет возможности отменить задержку. Например, если вы хотите сделать изображение видимым, подождать пять секунд и снова скрыть его, вы можете использовать delay следующим образом:


$("img").fadeIn(1000).delay(5000).fadeOut(1000);

Для всего остального лучше использовать setTimeout.

Наконец, если вам нужно несколько раз выполнить код после определенной задержки, лучше подойдет функция setInterval. Вы можете прочитаь о ней подробнее здесь .

Заключение

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

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться