HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Отдельное место в асинхронном мире занимают таймеры. Они позволяют отложить выполнение какой-либо функции "на потом". Наиболее важная функция для работы с таймерами - setTimeout(f, delay)</p>
1 <p>Отдельное место в асинхронном мире занимают таймеры. Они позволяют отложить выполнение какой-либо функции "на потом". Наиболее важная функция для работы с таймерами - setTimeout(f, delay)</p>
2 <p>В коде выше функция f выполнится не раньше, чем через секунду. Об этом нам говорит второй параметр, в который передаётся время, указанное в миллисекундах, после которого запустится функция, указанная первым параметром.</p>
2 <p>В коде выше функция f выполнится не раньше, чем через секунду. Об этом нам говорит второй параметр, в который передаётся время, указанное в миллисекундах, после которого запустится функция, указанная первым параметром.</p>
3 <p>Для чего нужны таймеры? У них много разных применений. Если говорить про браузер, то это могут быть автоматически скрываемые элементы: например, нотификации. Другой пример - это регулярный (например, раз в 5 секунд) Ajax-запрос для получения новых данных. На сервере таймеры используются реже, но тоже встречаются: с помощью них можно разбить объёмную синхронную операцию на несколько кусков, давая возможность выполниться другому коду.</p>
3 <p>Для чего нужны таймеры? У них много разных применений. Если говорить про браузер, то это могут быть автоматически скрываемые элементы: например, нотификации. Другой пример - это регулярный (например, раз в 5 секунд) Ajax-запрос для получения новых данных. На сервере таймеры используются реже, но тоже встречаются: с помощью них можно разбить объёмную синхронную операцию на несколько кусков, давая возможность выполниться другому коду.</p>
4 <p><em>В операционных системах такое поведение называется кооперативной многозадачностью. Она позволяет создавать ощущение параллельного выполнения кода, даже если этого не происходит.</em></p>
4 <p><em>В операционных системах такое поведение называется кооперативной многозадачностью. Она позволяет создавать ощущение параллельного выполнения кода, даже если этого не происходит.</em></p>
5 <p>Функция, переданная в таймер, выполняется не в текущем стеке вызовов, а значит к таймерам применимы все те особенности и подходы, о которых мы говорили ранее. Ошибки, возникающие в таймерах, невозможно отследить с помощью<em>try/catch</em>, для этого нужно использовать колбеки.</p>
5 <p>Функция, переданная в таймер, выполняется не в текущем стеке вызовов, а значит к таймерам применимы все те особенности и подходы, о которых мы говорили ранее. Ошибки, возникающие в таймерах, невозможно отследить с помощью<em>try/catch</em>, для этого нужно использовать колбеки.</p>
6 <p>Запуск:</p>
6 <p>Запуск:</p>
7 <p>Попробуйте ответить на такой вопрос. Могут ли таймеры гарантировать точный запуск через указанный промежуток времени? На самом деле не могут. Все зависит от того, что выполняется прямо сейчас. Проверкой таймеров занимается рантайм в тот момент, когда в текущем стеке вызовов не осталось кода. Если запустить тяжелое вычисление, которое не прекращается долго, то все колбеки, все таймеры, будут ждать пока вычисление закончится. Фактически это означает, что в таймерах задается минимальное время, после которого их можно запускать.</p>
7 <p>Попробуйте ответить на такой вопрос. Могут ли таймеры гарантировать точный запуск через указанный промежуток времени? На самом деле не могут. Все зависит от того, что выполняется прямо сейчас. Проверкой таймеров занимается рантайм в тот момент, когда в текущем стеке вызовов не осталось кода. Если запустить тяжелое вычисление, которое не прекращается долго, то все колбеки, все таймеры, будут ждать пока вычисление закончится. Фактически это означает, что в таймерах задается минимальное время, после которого их можно запускать.</p>
8 <p>Эта особенность имеет два важных следствия:</p>
8 <p>Эта особенность имеет два важных следствия:</p>
9 <ul><li>Старайтесь минимизировать время выполнения долгих вычислений. Например, их можно разбивать на шаги.</li>
9 <ul><li>Старайтесь минимизировать время выполнения долгих вычислений. Например, их можно разбивать на шаги.</li>
10 <li>Не рассчитывайте на точность времени вызова. Оно всегда будет отличаться в большую сторону.</li>
10 <li>Не рассчитывайте на точность времени вызова. Оно всегда будет отличаться в большую сторону.</li>
11 </ul><p>Таймеры можно не только создавать, но и отменять. Вызов setTimeout возвращает специальное значение - идентификатор таймера. Если передать его в функцию clearTimeout, то таймер отменится:</p>
11 </ul><p>Таймеры можно не только создавать, но и отменять. Вызов setTimeout возвращает специальное значение - идентификатор таймера. Если передать его в функцию clearTimeout, то таймер отменится:</p>
12 <p>Запуск:</p>
12 <p>Запуск:</p>
13 <p><em>То, что асинхронная функция вернула идентификатор таймера, не противоречит тому, что мы ранее говорили про возврат в асинхронных функциях. Асинхронная функция не может вернуть результат выполнения асинхронной операции, но может вернуть что-нибудь другое, что делалось синхронно внутри нее. В случае таймеров, идентификатор таймера возвращается синхронно, а вот сам таймер выполняется асинхронно.</em></p>
13 <p><em>То, что асинхронная функция вернула идентификатор таймера, не противоречит тому, что мы ранее говорили про возврат в асинхронных функциях. Асинхронная функция не может вернуть результат выполнения асинхронной операции, но может вернуть что-нибудь другое, что делалось синхронно внутри нее. В случае таймеров, идентификатор таймера возвращается синхронно, а вот сам таймер выполняется асинхронно.</em></p>
14 <p>Частая ошибка новичков в том, что они передают в таймер не саму функцию, а делают её вызов. Обычно она встречается тогда, когда в функцию нужно передать некоторые заранее определённые аргументы:</p>
14 <p>Частая ошибка новичков в том, что они передают в таймер не саму функцию, а делают её вызов. Обычно она встречается тогда, когда в функцию нужно передать некоторые заранее определённые аргументы:</p>
15 <p>Запуск:</p>
15 <p>Запуск:</p>
16 <p>До последнего лога дело не дошло, потому что скрипт упал на вызове setTimeout, так как он ожидал на вход функцию, а пришла не функция (вызов в примере вернул значение undefined).</p>
16 <p>До последнего лога дело не дошло, потому что скрипт упал на вызове setTimeout, так как он ожидал на вход функцию, а пришла не функция (вызов в примере вернул значение undefined).</p>
17 <p>Передать данные внутрь функции можно тремя способами:</p>
17 <p>Передать данные внутрь функции можно тремя способами:</p>
18 <p><strong>Дополнительные параметры в setTimeout</strong></p>
18 <p><strong>Дополнительные параметры в setTimeout</strong></p>
19 <p>Все аргументы, переданные в setTimeout после второго аргумента (времени), автоматически становятся аргументами функции, которую вызовет таймер.</p>
19 <p>Все аргументы, переданные в setTimeout после второго аргумента (времени), автоматически становятся аргументами функции, которую вызовет таймер.</p>
20 <p><strong>Функция-обёртка</strong></p>
20 <p><strong>Функция-обёртка</strong></p>
21 <p>Наиболее распространённый способ - создание функции-обёртки. Такой способ лучше предыдущего из-за его прозрачности: сразу видно, что происходит.</p>
21 <p>Наиболее распространённый способ - создание функции-обёртки. Такой способ лучше предыдущего из-за его прозрачности: сразу видно, что происходит.</p>
22 <p><strong>bind</strong></p>
22 <p><strong>bind</strong></p>
23 <p>Последний способ - использовать функцию bind. Основное предназначение этой функции - смена контекста функции. Но она может использоваться и для частичного применения функции:</p>
23 <p>Последний способ - использовать функцию bind. Основное предназначение этой функции - смена контекста функции. Но она может использоваться и для частичного применения функции:</p>
24 <p>Вызов этой функции возвращает новую функцию с применёнными аргументами.</p>
24 <p>Вызов этой функции возвращает новую функцию с применёнными аргументами.</p>
25 <p>Важно понимать, что таймер не делает асинхронной операцию, которая выполняется при вызове функции, переданной в setTimeout - таймер лишь откладывает время её выполнения. Если сама операция синхронная, то после запуска она заблокирует основной поток выполнения программы, и все остальные будут ждать её завершения.</p>
25 <p>Важно понимать, что таймер не делает асинхронной операцию, которая выполняется при вызове функции, переданной в setTimeout - таймер лишь откладывает время её выполнения. Если сама операция синхронная, то после запуска она заблокирует основной поток выполнения программы, и все остальные будут ждать её завершения.</p>
26 <h2>setInterval</h2>
26 <h2>setInterval</h2>
27 <p>Функция setInterval имеет точно такую же сигнатуру, как и setTimeout. Смысл аргументов - тот же самый. Разница в том, что setInterval автоматически запускает функцию не один раз, а до тех пор, пока её явно не остановят через clearInterval. Время между запусками равно значению второго параметра.</p>
27 <p>Функция setInterval имеет точно такую же сигнатуру, как и setTimeout. Смысл аргументов - тот же самый. Разница в том, что setInterval автоматически запускает функцию не один раз, а до тех пор, пока её явно не остановят через clearInterval. Время между запусками равно значению второго параметра.</p>
28 <p>Таймер можно остановить изнутри, использовав в колбеке его<em>id</em>.</p>
28 <p>Таймер можно остановить изнутри, использовав в колбеке его<em>id</em>.</p>
29  
29