Статьи

Примеры функций jQuery setTimeout ()

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

set_timeout_2-01

Базовый пример setTimeout

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

Если вы не видите всплывающее окно открытым, посетите CodePen и запустите демо-версию там.

Синтаксис

Из документации MDN синтаксис для setTimeout выглядит следующим образом:

 var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]); var timeoutID = scope.setTimeout(function[, delay]); var timeoutID = scope.setTimeout(code[, delay]); 

где:

  • timeoutID — это числовой идентификатор, который можно использовать вместе с clearTimeout() для отмены таймера.
  • scope относится к интерфейсу Window или интерфейсу WorkerGlobalScope .
  • function — это функция, которая будет выполнена после истечения таймера.
  • code (в альтернативном синтаксисе) — это строка кода, которая должна быть выполнена.
  • delay — это количество миллисекунд, на которое должен быть задержан вызов функции. Если опущено, по умолчанию это 0.

Примечание: квадратные скобки [] обозначают необязательные параметры.

setTimeout против window.setTimeout

Вы заметите, что приведенный выше синтаксис использует scope.setTimeout . Почему это?

Что ж, при запуске кода в браузере scope будет ссылаться на объект глобального window . И setTimeout и window.setTimeout ссылаются на одну и ту же функцию, с той лишь разницей, что во втором выражении мы 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 предлагает больше информации по вышеуказанным пунктам.

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

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

В следующем примере мы выбираем случайное приветствие из массива greetings и передаем это случайное приветствие в качестве параметра функции greet , которая выполняется setTimeout с задержкой в ​​одну секунду:

 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(greet, 1000, randomGreeting); 

К сожалению, это не работает в IE9 или ниже, где параметры указаны как 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 

Причина этого вывода в том, что в первом примере this указывает на объект person , тогда как во втором примере this указывает на объект глобального window (у которого нет свойства firstName ).

Чтобы противодействовать этому, существуют различные меры:

Явно установите значение this

Вы можете сделать это, используя bind , метод, который создает новую функцию, которой при вызове присваивается ключевое слово this с указанным значением (в нашем случае это объект person ). Это даст нам:

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

Примечание: bind было введено в ECMAScript 5, поэтому будет работать только в более современных браузерах . Вы можете прочитать больше об этом (и других методах установки значения this ) в этой статье SitePoint .

Используйте библиотеку

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

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

Использование функций стрелок с setTimeout

Функции стрелок были введены с ES6. У них намного более короткий синтаксис, чем у обычной функции:

 (param1, param2, paramN) => expression 

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

Используя обычную функцию:

 const person = { firstName: "Jim", introduce: function() { console.log(`Hi, I'm ${this.firstName}`); } }; person.introduce(); // Hi, I'm Jim 

Используя функцию стрелки:

 const person = { firstName: "Jim", introduce: () => { console.log(`Hi, I'm ${this.firstName}`); } }; person.introduce(); // Hi, I'm undefined 

Во втором примере this указывает на объект глобального window (у которого нет свойства firstName ).

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

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

Это не будет работать при использовании функции стрелки в методе introduce , так как функция стрелки не имеет своего собственного значения this . Метод по-прежнему будет регистрироваться как undefined .

Чистый код с функциями стрелок и setTimeout

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

Код как это …

 var person = { firstName: "Jim", delayedIntroduce: function() { setTimeout( function() { console.log("Hi, I'm " + this.firstName); } .bind(this) , 1000); } } person.delayedIntroduce(); 

… Можно переписать более кратко с помощью функции стрелки:

 const person = { firstName: "Jim", delayedIntroduce() { setTimeout( () => { console.log(`Hi, I'm ${this.firstName}`); }, 1000 ); } } person.delayedIntroduce(); 

Если вы хотите ознакомиться с функциями стрелок, ознакомьтесь с разделом Функции стрелок ES6: толстый и краткий синтаксис в JavaScript .

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

Возвращаемое значение setTimeout — это числовой идентификатор, который можно использовать для отмены таймера в сочетании с функцией clearTimeout :

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

Давайте посмотрим это в действии. В следующем пене, если вы нажмете кнопку « Пуск» , начнется обратный отсчет. Если обратный отсчет завершится, котята получат его. Однако, если вы нажмете кнопку остановки отсчета , таймер будет остановлен и сброшен. (Если вы не видите крутого эффекта, когда обратный отсчет достигает нуля, перезапустите перо, используя кнопку в правом нижнем углу встраивания.)

Завершение

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

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

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

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

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

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

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

Вывод

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

Если вы хотите узнать больше, в SitePoint Premium есть целая библиотека книг по JavaScript .

Если вы хотите обсудить содержание этой статьи, пожалуйста, сделайте это в комментариях. Однако, если вы столкнулись с проблемой кодирования, касающейся использования setTimeout (или чего-то еще, действительно), тогда, пожалуйста, перейдите на форумы SitePoint . Вы можете войти с помощью (Google, Facebook, Twitter, Yahoo, GitHub или путем создания учетной записи). Затем перейдите на форум JavaScript и начните обсуждение вашей проблемы.