Создание сайтов в Москве. Функция setTimeout JavaScript: руководство с примерами

 
 

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

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

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

См. модальное окно Pen Delayed Magnific Popup от SitePoint (@SitePoint) на CodePen.

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

Синтаксис

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

var timeoutID = scope.setTimeout (function[, delay, arg1, arg2,... ]) ;

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

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

куда:

timeoutID— это числовой идентификатор, который можно использовать вместе с clearTimeout для отмены таймера.

scopeотносится к интерфейсу Window или интерфейсу WorkerGlobalScope.

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

code— это альтернативный синтаксис, который позволяет включать строку вместо функции, которая компилируется и выполняется по истечении времени таймера.

delay- количество миллисекунд, на которое должен быть задержан вызов функции. Если этот параметр опущен, по умолчанию он равен 0.

arg1,..., argNявляются дополнительными аргументами, передаваемыми функции, указанной параметром function.

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

setTimeout против окна.setTimeout

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

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

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

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

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

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

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

function greet () {

alert ('Howdy!') ;

}

setTimeout (greet, 2000) ;

Переменная, которая ссылается на функцию (выражение функции):

const greet = function () {

alert ('Howdy!') ;

};

setTimeout (greet, 2000) ;

Или анонимная функция:

setTimeout (() => { alert ('Howdy!') ; }, 2000) ;

Как отмечалось выше, для его выполнения также можно передать setTimeoutстроку кода:

setTimeout ('alert («Howdy!») ;', 2000) ;

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

Его трудно читать (и, следовательно, трудно поддерживать и/или отлаживать).

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

Это медленнее, чем альтернативы, так как он должен вызывать интерпретатор JS.

Этот вопрос о переполнении стека предлагает дополнительную информацию по вышеуказанным пунктам.

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

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

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

function makeTalk (animal) {

const noises = {

cat: 'purr’,

dog: 'woof’,

cow: 'moo’,

pig: 'oink’,

}

console.log (`A ${animal} goes ${noises[animal]}. `) ;

}

function getRandom (arr) {

return arr[Math.floor (Math.random () *arr.length) ];

}

const animals = ['cat’, 'dog’, 'cow’, 'pig’];

const randomAnimal = getRandom (animals) ;

setTimeout (() => {

makeTalk (randomAnimal) ;

}, 1000) ;

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

const getRandom = arr => arr[Math.floor (Math.random () *arr.length) ];

Мы перейдем к стрелочным функциям в следующем разделе.

Альтернативный метод

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

Что касается нашего предыдущего примера, это даст нам:

setTimeout (makeTalk, 1000, randomAnimal) ;

К сожалению, это не работает в IE9 и ниже, где параметры отображаются как undefined. Если вам незавидно приходится поддерживать IE9, на MDN доступен полифилл.

Проблема сthis

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

const dog = {

sound: 'woof’,

bark () {

console.log (`Rover says ${this.sound}! `) ;

}

};

dog.bark () ;

// Outputs: Rover says woof!

setTimeout (dog.bark, 50) ;

// Outputs: Rover says undefined!

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

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

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

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

setTimeout (dog.bark.bind (dog), 50) ;

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

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

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

setTimeout ($.proxy (dog.bark, dog), 50) ;

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

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

(param1, param2, paramN) => expression

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

Использование обычной функции:

const dog = {

sound: 'woof’,

bark () {

console.log (`Rover says ${this.sound}! `) ;

}

};

dog.bark () ;

// Rover says woof!

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

const dog = {

sound: 'woof’,

bark: () => {

console.log (`Rover says ${this.sound}! `) ;

}

};

dog.bark () ;

// Rover says undefined!

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

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

setTimeout (dog.bark.bind (dog), 50) ;

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

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

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

Рассмотрим такой код:

const dog = {

sound: 'woof’,

delayedBark () {

setTimeout (

function () {

console.log (`Rover says ${this.sound}! `) ;

}

.bind (this)

, 1000) ;

}

}

dog.delayedBark () ;

Его можно переписать более кратко с помощью стрелочной функции:

const dog = {

sound: 'woof’,

delayedBark () {

setTimeout (

() => { console.log (`Rover says ${this.sound}! `) ; }, 1000

) ;

}

}

dog.delayedBark () ;

Если вам нужен учебник по стрелочным функциям, прочтите «Стрелочные функции ES6: жирный и лаконичный синтаксис в JavaScript «.

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

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

const timer = setTimeout (myFunction, 3000) ;

clearTimeout (timer) ;

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

См. Pen SetTimeout Kittens от SitePoint (@SitePoint) на CodePen.

Подведение итогов

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

console.log (1) ;

setTimeout (() => { console.log (2) ; }, 0) ;

console.log (3) ;

// Outputs: 1, 3, 2

Хотя мы звоним setTimeoutс задержкой в ​​ноль секунд, номера по-прежнему регистрируются не по порядку. Это связано setTimeoutс тем, что по истечении времени таймера механизм JavaScript помещает свою функцию обратного вызова в очередь после других console.logоператоров для выполнения.

Если вы хотите узнать больше о том, что происходит при запуске JavaScript, я настоятельно рекомендую это видео с JSConf 2014: Что вообще такое, черт возьми, цикл обработки событий?

запросАнимацияКадр ()

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

При создании анимации мы должны отдавать предпочтение requestAnimationFrameиспользованию setTimeout, так как оно будет срабатывать примерно шестьдесят раз в секунду, в отличие от setTimeout, которое вызывается как минимум через nмиллисекунды. С помощью использования requestAnimationFrameмы можем избежать двойного изменения чего-либо между двумя обновлениями кадра.

Вот пример того, как использовать requestAnimationFrameанимацию divэлемента на экране:

const div = document.querySelector ('#rectangle’) ;

let leftPos = 0;

function animateDiv () {

leftPos += 1;

div.style.left = `${leftPos}px`;

if (leftPos < 100) requestAnimationFrame (animateDiv) ;

}

requestAnimationFrame (animateDiv) ;

Конечно, вы могли бы добиться того же, используя setTimeout:

const div = document.querySelector ('#rectangle’) ;

let leftPos = 0;

function animateDiv () {

leftPos += 1;

div.style.left = `${leftPos}px`;

if (leftPos < 100) setTimeout (animateDiv, 1000/60) ;

}

animateDiv () ;

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

См.

анимацию пера с помощью requestAnimationFrame от SitePoint (@SitePoint)

на CodePen.

jQuery.delay ()

Наконец, я хотел бы прояснить любую путаницу между использованием нативной setTimeoutфункции JavaScript и метода задержки jQuery.

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

$ ('img’).fadeIn (1000).delay (5000).fadeOut (1000) ;

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

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

Вывод

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

Если вы столкнулись с проблемой кодирования, связанной с использованием setTimeout (или с чем-то еще), пожалуйста, посетите форумы SitePoint, где мы будем рады помочь.

3D-печать5GABC-анализAndroidAppleAppStoreAsusCall-центрChatGPTCRMDellDNSDrupalExcelFacebookFMCGGoogleHuaweiInstagramiPhoneLinkedInLinuxMagentoMicrosoftNvidiaOpenCartPlayStationPOS материалPPC-специалистRuTubeSamsungSEO-услугиSMMSnapchatSonyStarlinkTikTokTwitterUbuntuUp-saleViasatVPNWhatsAppWindowsWordPressXiaomiYouTubeZoomАвдеевкаАктивные продажиАкцияАлександровск ЛНРАлмазнаяАлчевскАмвросиевкаАнализ конкурентовАнализ продажАнтимерчандайзингАнтрацитАртемовскАртемовск ЛНРАссортиментная политикаБелгородБелицкоеБелозерскоеБердянскБизнес-идеи (стартапы)БрендБрянкаБукингВахрушевоВендорВидеоВикипедияВирусная рекламаВирусный маркетингВладивостокВнутренние продажиВнутренний маркетингВолгоградВолновахаВоронежГорловкаГорнякГорскоеДебальцевоДебиторкаДебиторская задолженностьДезинтермедитацияДзержинскДивизионная система управленияДизайнДимитровДирект-маркетингДисконтДистрибьюторДистрибьюцияДобропольеДокучаевскДоменДружковкаЕкатеринбургЕнакиевоЖдановкаЗапорожьеЗимогорьеЗолотоеЗоринскЗугрэсИжевскИловайскИрминоКазаньКалининградКировскКировскоеКомсомольскоеКонстантиновкаКонтент-маркетингКонтент-планКопирайтингКраматорскКрасноармейскКрасногоровкаКраснодарКраснодонКраснопартизанскКрасный ЛиманКрасный ЛучКременнаяКураховоКурскЛисичанскЛуганскЛутугиноМакеевкаМариупольМаркетингМаркетинговая информацияМаркетинговые исследованияМаркетинговый каналМаркетинг услугМаркетологМарьинкаМедиаМелекиноМелитопольМенеджментМерчандайзерМерчандайзингМиусинскМолодогвардейскМоскваМоспиноНижний НовгородНиколаевНиколаевкаНишевой маркетингНовоазовскНовогродовкаНоводружескНовосибирскНумерическая дистрибьюцияОдессаОмскОтдел маркетингаПартизанский маркетингПервомайскПеревальскПетровскоеПлата за кликПоисковая оптимизацияПопаснаяПравило ПаретоПривольеПрогнозирование продажПродвижение сайтов в ДонецкеПроизводство видеоПромоПромоушнПрямой маркетингРабота для маркетологаРабота для студентаРазработка приложенийРаспродажаРегиональные продажиРекламаРеклама на асфальтеРемаркетингРетро-бонусРибейтРитейлРовенькиРодинскоеРостов-на-ДонуРубежноеСамараСанкт-ПетербургСаратовСватовоСвердловскСветлодарскСвятогорскСевастопольСеверодонецкСеверскСедовоСейлз промоушнСелидовоСимферопольСинергияСколковоСлавянскСнежноеСоздание сайтов в ДонецкеСоледарСоциальные сетиСочиСтаробельскСтаробешевоСтахановСтимулирование сбытаСуходольскСчастьеТелемаркетингТельмановоТираспольТорговый представительТорезТрейд маркетингТрейд промоушнТюменьУглегорскУгледарУкраинскХабаровскХарцызскХерсонХостингЦелевая аудиторияЦифровой маркетингЧасов ЯрЧелябинскШахтерскЮжно-СахалинскЮнокоммунаровскЯндексЯсиноватая