Лекция
Привет, сегодня поговорим про клонировать settimeout, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое клонировать settimeout, setinterval , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).
setTimeout
clearTimeout
setInterval
setTimeout
при помощи NFEsetInterval
setTimeout
setTimeout(func, 0)
Почти все реализации JavaScript имеют внутренний таймер-планировщик, который позволяет задавать вызов функции через заданный период времени.
В частности, эта возможность поддерживается в браузерах и в сервере Node.JS.
setTimeout
Синтаксис:
var timerId = setTimeout(func/code, delay[, arg1, arg2...]) |
Параметры:
func/code
delay
arg1
, arg2
…Исполнение функции произойдет спустя время, указанное в параметре delay
.
Например, следующий код вызовет alert('Привет')
через одну секунду:
1 |
function func() { |
2 |
alert( 'Привет' ); |
3 |
} |
4 |
setTimeout(func, 1000); |
Если первый аргумент является строкой, то интерпретатор создает анонимную функцию из этой строки.
То есть такая запись работает точно так же:
1 |
setTimeout( "alert('Привет')" , 1000); |
Использование строк не рекомендуется, так как они могут вызвать проблемы при минимизации кода, и, вообще, сама возможность использовать строку сохраняется лишь для совместимости.
Вместо них используйте анонимные функции:
1 |
setTimeout( function () { alert( 'Привет' ) }, 1000); |
clearTimeout
Функция setTimeout
возвращает идентификатор timerId
, который можно использовать для отмены действия.
Синтаксис: clearTimeout(timerId)
.
В следующем примере мы ставим таймаут, а затем удаляем (передумали). В результате ничего не происходит.
1 |
var timerId = setTimeout( function () { alert(1) }, 1000); |
2 |
3 |
clearTimeout(timerId); |
setInterval
Метод setInterval
имеет синтаксис, аналогичный setTimeout
.
var timerId = setInterval(func/code, delay[, arg1, arg2...]) |
Смысл аргументов — тот же самый. Но, в отличие от setTimeout
, он запускает выполнение функции не один раз, а регулярно повторяет ее через указанный интервал времени. Остановить исполнение можно вызовом clearInterval(timerId)
.
Следующий пример при запуске станет выводить сообщение каждые две секунды, пока не пройдет 5 секунд:
1 |
var timerId = setInterval( function () { |
2 |
alert( "тик" ); |
3 |
}, 2000); |
4 |
5 |
setTimeout( function () { |
6 |
clearInterval(timerId); |
7 |
alert( 'стоп' ); |
8 |
}, 5000); |
Что будет, если долго не жать OK
на появившемся alert
?
Это зависит от браузера.
В браузерах Chrome, Opera и Safari внутренний таймер «замирает» во время показаalert/confirm/prompt
и продолжит отсчет с момента закрытия. Поэтому после закрытия alert
в любом случае пройдет две секунды до следующего тика.
А вот в IE и Firefox внутренний таймер продолжит идти, и, если долго не закрыватьalert
, то может подойти время следующего вызова. Но, так как браузер не может показать новый alert
, пока открыт этот, он будет ждать нажатия OK
, и потом покажет новый alert
сразу же.
setTimeout
при помощи NFEБывает так, что функцию необходимо выполнять с определенным интервалом, но следующий интервал определяется исходя из ее последнего результата.
Реальный пример — мы пытаемся подсоединиться к серверу получить данные, но это не получается, например потому что сервер перегружен (мало ли что, может атака на него).
Чтобы не грузить сервер еще больше, мы сделаем следующий запрос данных через чуть больший интервал, потом, если проблема еще есть — еще через больший и так до максимального интервала, когда мы прекращаем автозапросы и предлагаем пользователю решить, что делать. Примерно так поступает, к примеру, Gmail.
Здесь, чтобы не отвлекаться на другие темы,
Например, будем выводить alert
со случайным интервалом:
Например, мы пишем приложение, которое пытается раз в секунду присоединиться к серверу и получить с него данные. Это будет делать функция connect()
setInterval
Вызов setInterval(функция, задержка)
ставит функцию
на исполнение через указанный интервал времени. Но здесь есть тонкость.
На самом деле пауза между вызовами меньше, чем указанный интервал.
Для примера, возьмем setInterval(function() { func(i++) }, 100)
. Она выполняет func
каждые 100 мс, каждый раз увеличивая значение счетчика.
На картинке ниже, красный блок - это время исполнения func
. Время между блоком — это время между запусками функции, и оно меньше, чем установленная задержка!
То есть, браузер инициирует запуск функции аккуратно каждые 100мс
, без учета времени выполнения самой функции.
Бывает, что исполнение функции занимает больше времени, чем задержка. Например, функция сложная, а задержка маленькая. Или функция содержит операторы alert/confirm/prompt
, которые блокируют поток выполнения. В этом случае начинаются интересные вещи
Если запуск функции невозможен, потому что браузер занят — она становится в очередь и выполнится, как только браузер освободится.
Изображение ниже иллюстрирует происходящее для функции, которая долго исполняется.
Вызов функции, инициированный setInterval
, добавляется в очередь и незамедлительно происходит, когда это становится возможным:
Второй запуск функции происходит сразу же после окончания первого:
Больше одного раза в очередь выполнение не ставится.
Если выполнение функции занимает больше времени, чем несколько запланированных исполнений, то в очереди она все равно будет стоять один раз. Так что «накопления» запусков не происходит.
На изображении ниже setInterval
пытается выполнить функцию в 200 мс и ставит вызов в очередь. В 300 мс и 400 мс таймер пробуждается снова, но ничего не просходит.
Давайте посмотрим на примере, как это работает.
Внутренний таймер в браузерах Safari/Chrome во время показаalert/confirm/prompt
не «тикает». Если до исполнения оставалось 3 секунды, то даже при показе alert
на протяжении минуты — задержка остается 3 секунды.
Поэтому пример ниже не воспроизводится в этих браузерах. В других браузерах все в порядке.
alert
. Пока модальное окошко отображается, исполнение JavaScript блокируется. Подождите немного и нажмите OK.Стоп
.
1 |
< input type = "button" onclick = "clearInterval(timer)" value = "Стоп" > |
2 |
3 |
<script> |
4 |
var i = 1; |
5 |
var timer = setInterval( function () { alert(i++) }, 2000); |
6 |
</script> |
Происходит следующее.
alert
— исполнение блокируется и остается заблокированным все время, пока alert
отображается.
Вызов setInterval(функция, задержка)
не гарантирует реальной задержки междуисполнениями.
Бывают случаи, когда реальная задержка больше или меньше заданной. Вообще, не факт, что будет хоть какая-то задержка.
setTimeout
В случаях, когда нужно не просто регулярное повторение, а обязательна задержка между запусками, используется повторная установка setTimeout
при каждом выполнении функции.
Ниже — пример, который выдает alert
с интервалами 2 секунды между ними.
01 |
< input type = "button" onclick = "clearTimeout(timer)" value = "Стоп" > |
02 |
03 |
<script> |
04 |
var i = 1; |
05 |
06 |
var timer = setTimeout( function run() { |
07 |
alert(i++); |
08 |
timer = setTimeout(run, 2000); |
09 |
}, 2000); |
10 |
11 |
</script> |
На временной линии выполнения будут фиксированные задержки между запусками. Иллюстрация для задержки 100мс:
У браузерного таймера есть минимальная возможная задержка. Она меняется от примерно нуля до 4мс в современных браузерах. Об этом говорит сайт https://intellect.icu . В более старых она может быть больше и достигать 15мс.
По стандарту, минимальная задержка составляет 4мс. Так что нет разницы междуsetTimeout(..,1)
и setTimeout(..,4)
.
Посмотреть минимальное разрешение «вживую» можно на следующем примере.
В примере ниже находятся DIV'ы
, каждый удлиняется вызовом setInterval
с указанной в нем задержкой — от 0мс (сверху) до 20мс (внизу).
Запустите его в различных браузерах, в частности, в Chrome и Firefox. Вы наверняка заметите, что несколько первых DIV'ов
анимируются с одинаковой скоростью. Это как раз потому, что слишком маленькие задержки таймер не различает.
Открыть в новом окне Открыть в песочнице
В поведении setTimeout
и setInterval
с нулевой задержкой есть браузерные особенности.
setTimeout(.., 0)
— то же самое, что setTimeout(.., 4)
. Оно выполняется реже, чем setTimeout(.. ,2)
. Это особенность данного браузера.setInterval(.., 0)
не сработает. Это касается именноsetInterval
, т.е. setTimeout(.., 0)
работает нормально.Пример ниже реализует такую же анимацию, но через setTimeout
. Если посмотреть его в различных браузерах, то можно заметить отличия от setInterval
.
Открыть в новом окне Открыть в песочнице
В ряде случаев задержка может быть не 4мс, а 30мс или даже 1000мс.
setTimeout/setInterval
, даже если вкладка неактивна.
При этом ряд из них (Chrome, FF, IE10) снижают минимальную частоту таймера, до 1 раза в секунду. Получается, что в «фоновой» вкладке будет срабатывать таймер, но редко.
setInterval
будут пропущены.Вывод: на частоту 4мс стоит ориентироваться, но не стоит рассчитывать.
Посмотрим снижении частоты в действии на небольшом примере.
При клике на кнопку ниже запускается setInterval(..., 90)
, который выводит список интервалов времени между 25 последними срабатываниями таймера. Запустите его. Перейдите на другую вкладку и вернитесь.
Если ваш браузер увеличивает таймаут при фоновом выполнении вкладки, то вы увидите увеличенные интервалы, помеченные красным.
Кроме того, вы точно увидите, что таймер не является идеально точным
Код, который используется в примере выше и считает интервалы времени между вызовами, выглядит примерно так:
01 |
var timeMark = new Date; |
02 |
setTimeout( function go() { |
03 |
var diff = new Date - timeMark; |
04 |
05 |
// вывести очередную задержку в консоль вместо страницы |
06 |
console.log(diff); |
07 |
08 |
// запомним время в самом конце, |
09 |
// чтобы измерить задержку именно между вызовами |
10 |
timeMark = new Date; |
11 |
12 |
setTimeout(go, 100); |
13 |
}, 100); |
Нулевой или небольшой таймаут также используют, чтобы разорвать поток выполнения «тяжелых» скриптов.
Например, скрипт для подсветки синтаксиса должен проанализировать код, создать много цветных элементов для подсветки и добавить их в документ — на большом файле это займет много времени.
Браузер сначала будет есть 100% процессора, а затем может выдать сообщение о том, что скрипт выполняется слишком долго.
Для того, чтобы этого избежать, сложная задача разбивается на части, выполнение каждой части запускается через мини-интервал после предыдущей, чтобы дать браузеру время. Например, планируется подсветка 20 строк каждые 10мс.
setTimeout(func, 0)
Этот трюк достоин войти в анналы JavaScript-хаков.
Функцию оборачивают в setTimeout(func, 0)
, если хотят запустить ее после окончания текущего скрипта.
Дело в том, что setTimeout
никогда не выполняет функцию сразу. Он лишь планирует ее выполнение. Но интерпретатор JavaScript начнет выполнять запланированные функции лишь после выполнения текущего скрипта.
По стандарту, setTimeout
в любом случае не может выполнить функцию с задержкой 0
. Как мы говорили раньше, обычно задержка составит 4мс. Но главное здесь именно то, что выполнение в любом случае будет после выполнения текущего кода.
Например:
01 |
var result; |
02 |
03 |
function showResult() { |
04 |
alert(result); |
05 |
} |
06 |
07 |
setTimeout(showResult, 0); |
08 |
09 |
result = 2*2; |
10 |
11 |
// выведет 4 |
Позже, в главе Управление порядком обработки, setTimeout(…0), мы рассмотрим различные применения этого трюка при работе с событиями.
Методы setInterval(func, delay)
и setTimeout(func, delay)
позволяют запускать func
регулярно/один раз через delay
миллисекунд.
Оба метода возвращают идентификатор таймера. Его используют для остановки выполнения вызовомclearInterval/clearTimeout
.
setInterval |
setTimeout |
|
Тайминг | Идет вызов строго по таймеру. Если интерпретатор занят — один вызов становится в очередь.
Время выполнения функции не учитывается, поэтому промежуток времени от окончания одного запуска до начала другого может быть различным. |
Рекурсивный вызов setTimeout используется вместо setInterval там, где нужна фиксированная пауза между выполнениями. |
Задержка | Минимальная задержка: 4мс. | Минимальная задержка: 4мс. |
Минимальная задержка для этих методов в современных браузерах различна и колеблется от примерно нуля до 4мс. В старых браузерах она может доходить до 15мс. | ||
Браузерные особенности | В IE не работает задержка 0 . |
В Opera нулевая задержка эквивалентна 4мс, остальные задержки обрабатываются точно, в том числе нестандартные 1мс, 2мс и 3мс. |
К сожалению, в одной статье не просто дать все знания про клонировать settimeout. Но я - старался. Если ты проявишь интерес к раскрытию подробностей,я обязательно напишу продолжение! Надеюсь, что теперь ты понял что такое клонировать settimeout, setinterval и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)