Функция js settimout и sleep в javascript

setTimeout(…,0)

‘un farklı bir kullanım şekli daha bulunmakta:

Bu ‘ın mümkün olduğu anda zamanlanmasını sağlar. Fakat zamanlayıcı bunu sadece o anki kod işlemi bittiğinde gerçekleştirir.

Bundan dolayı zamanlayıcı o anki işin “hemen arkasından” çalışmaya başlar. Diğer bir deyişle “asenkron”.

Örneğin aşağıdaki kod önce “Merhaba” ve hemen arkasından “Dünya” yazdırır.

İlk satırda “çağrıyı 0ms sonra sıraya koy” demektir. Fakat zamanlayıcı bunu “önce sırayı kontrol et”’ten sonra bakar yani o anki kodu çalıştırdıktan sonra. Bundan dolayı önce yazılır sonra.

ile CPU-aç görevlerin kullanılabilmesi şöyle bir yöntem kullanılabilir.

Örneğin, yazıların renklerini değiştiren ( şu anki sayfa gibi ) bir uygulama tam olarak CPU-aç bir uygulamadır. Analiz eder, bir çok renkli eleman yaratır, bunları dökümana ekler dosya büyüdükçe bu da gittikçe daha fazla işlemci gerektirir. Hatta tarayıcının «hang » durumuna yani tepki vermemesine kadar gidebilir, bu da kabul edilemez.

Bundan dolayı uzun metinleri ayırabiliriz. Önce 100 satır, sonra diğer bir 100 satır vs.

Daha basit bir örnekten anlatmaya çalışırsak. Bir fonksiyonunuz olsun ve ‘den ‘a kadar saysın

Eğer kodu çalıştırırsanız işlemci tepki vermemeye başlar. Sunucu tabanlı JS kodlarında bu kolay bir şekilde fark edilebilir fakat eğer bu kodu tarayıcı üzerinde çalıştırıyorsanız diğer butonlara tıkladığınızda JavaScript’in durduğunu ve bunun bitene kadar da başka birşeyin çalışmadığını görürsünüz.

Hatta taryıcı “bu kodun çalışması uzun zaman alıyor” uyarısı verebilir.

Kodu ile bölecek olursak:

Şimdi tarayıcı ekranı “sayma işlemi” gerçekleşirken tamamen çalışır durumdadır.

İşin bir bölümü şu şekilde yapılır

  1. İlk çalışma: .
  2. ikinci çalışma:
  3. … bu şekilde while nin ‘e bölünüp bölünmediğine kadar.

Eğer işlem hala bitmemişse zamanlayıcısı tekrar çalışır.

Sayaç çalışırken duraklama yapılması JavaScript motoruna “nefes alması” ve başka iş yapabilmesi için zaman sağlar.

Dikkat edilmesi gereken nokta: kullanılarak ve kullanılmadan yapılan iki testin çalışma süreleri çok farklı değildir.

Bu süreleri daha da yakınlaştırabilmek için neler yapılabilir bakalım.

Zamanlamayı fonksiyonunun başına alalım:

Şimdi ise ile başlıyoruz ve fonksiyonunun birden fazla çağırılacağınız biliyoruz.

Çalıştırırsanız belirgin biçimde daha kısa süreceğini göreceksiniz.

Browserdaki iç içe zamanlayıcıların arasında bulunan minimum gecikmeler

Tarayıcıda, iç içe zamanlayıcıların kullanımına ait bir limit bulunmaktadır. dediğine göre: “5 iç içe zamanlayıcıdan sonra, döngü en az 4 ms durmak zorundadır.”

Bunu aşağıdaki bulunan örnekte gösterelim. çağrısı kendisini sonra tekrarn çağırıyor. Her bir çağrı bir öncekinin zamanını dizisinden hatırlıyor. Gecikme nasıl olacak bakalım:

İlk zamanlayıcılar anında çalışacaktır ( dökümantasyonda yazdığı gibi ) bundan dosnra gecikmeler oyuna dahil olur.

Bu limitasyonların nedeni de yine eski zamanlara dayanmaktadır. Çoğu kod bu prensibe göre çalıştığından dolayı bu kurallar devam etmektedir.

Sunucu tabanlı JavaScript için ise bu kısıtlama geçerli değildir. Ayrıca anlık olarak asenkronron işlerin zamanlaması amacıyla başka yollar da bulunmaktadır. Örneğin process.nextTick ve setImmediate gibi. Yani buradaki kısıtlamanın tarayıcı bazlı olduğu sonucunu çıkarabilirsiniz.

Tarayıcı taraflı kodların diğer bir yararı ise kullanıcıya progresss bar(ilerleme çubuğu) tarzında görselleri sunabilmesidir. Tarayıcı genelde “tekrar boyama” kod tekrarlandıktan sonra ( repainting) işlemi yaptığından.

Bundan dolayı diyelim ki çok büyük işler yapan bir fonksiyon olsa bile, dökümanda bulunan değişiklik bu işlem tamamlandıktan sonra gerçekleşir.

ÖrneğiN:

Bunu çalıştıdığınızda ‘nin değişikliği tüm sayma işlemi bittikten sonra görünür hale gelir.

eğer bunu ile parçalara bölecek olursak bu defa daha güzel bir şekilde görünecektir.

Artık nin yükselen değerini gösterecektir.

Zero delay setTimeout

There’s a special use case: , or just .

This schedules the execution of as soon as possible. But the scheduler will invoke it only after the currently executing script is complete.

So the function is scheduled to run “right after” the current script.

For instance, this outputs “Hello”, then immediately “World”:

The first line “puts the call into calendar after 0ms”. But the scheduler will only “check the calendar” after the current script is complete, so is first, and – after it.

There are also advanced browser-related use cases of zero-delay timeout, that we’ll discuss in the chapter Event loop: microtasks and macrotasks.

Zero delay is in fact not zero (in a browser)

In the browser, there’s a limitation of how often nested timers can run. The says: “after five nested timers, the interval is forced to be at least 4 milliseconds.”.

Let’s demonstrate what it means with the example below. The call in it re-schedules itself with zero delay. Each call remembers the real time from the previous one in the array. What do the real delays look like? Let’s see:

First timers run immediately (just as written in the spec), and then we see . The 4+ ms obligatory delay between invocations comes into play.

The similar thing happens if we use instead of : runs few times with zero-delay, and afterwards with 4+ ms delay.

That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons.

For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like for Node.js. So this note is browser-specific.

setTimeout()

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

setTimeout ( expression, timeout );

Тут в JavaScript коде запустится по прошествии миллисекунд, указанных в аргументе .

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

Вот ещё один пример:

<input type="button" name="sayHello" value="Wait for my Hello!"onclick="setTimeout('alert(\'Hello!\')', 4000)"/>

При нажатии на кнопку запускается метод. Выражение, запуск которого по вашему предусмотрению должен произойти с задержкой в 4000ms или 4 секунды, уже передано.

Тут стоит обратить внимание на то, что не останавливает выполнение дальнейшего скрипта во время периода тайм-аута. Он просто откладывает выполнение указанного блока кода на заложенное количество времени

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

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

Для примера, код ниже, вызывает через одну секунду:

function sayHello() {alert('Hello');}setTimeout(sayHello, 1000);

Вы можете также передавать аргументы вместе с функцией, например, как тут:

function sayHello(message, person) {alert( message + ', '+ person );}setTimeout(sayHello, 1000, "Hi", "Monica"); // Hi, Monica

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

Если первый аргумент это строка, то JavaScript может создать из неё функцию. Так что вот это тоже сработает:

setTimeout("alert('Hello')", 1000);

Но применение такого метода не рекомендуется, лучше используйте функции, как тут:

setTimeout(() => alert('Hello'), 1000);

Управление временным континуумом с Node.js

API Node.js предоставляет несколько способов планирования кода, который нужно
выполнить, в какой-то момент в будущем. Приведенные ниже функции могут показатья знакомыми, так как
они доступны в большинстве браузеров, но Node.js на самом деле предоставляет
свою реализацию этих методов. Таймеры очень тесно интегрируются с системой, и, несмотря на то,
что API Node.js отражает API браузера, все равно имеются некоторые различия в реализации.

«Когда я скажу» Выполнение ~

может использоваться для планирования выполнения кода после назначенного
количества миллисекунд. Эта функция аналогична из JavaScript API браузера, однако строка кода не может передаваться
в качестве аргумента для выполнения.

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

Функция выполнится через время, максимально приближенное к
1500 миллисекундам (или 1.5 секунды), из-за вызова .

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

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

«Сразу после этого» Выполнение ~

выполнит код в конце текущего цикла событий.
Этот код будет выполняться после любых операций ввода-вывода в текущем цикле событий и
перед любым запланированными таймерами для следующего цикла событий. Такое выполнение кода
можно рассматривать как «сразу после этого», то есть любой код, следующий за вызовом
функции , будет выполняться до аргумента функции .

Первым аргументом будет функция, которую нужно выполнить. Все последующие
аргументы будут переданы функции при ее выполнении. Вот пример:

Функция, переданная в , будет выполнена после того,
как будет выполнен весь исполняемый код, и в консоли мы увидим следующее:

возвращает объект , который можно использовать для отмены
запланированного immediate (см. ниже).

Примечание: Не путайте и . Между ними есть
несколько основных различий. Во-первых, выполнится перед любыми ,
а также перед любыми запланированными операциями ввода/вывода. Во-вторых, не подлежит
отмене, имеется в виду, что после того как вы запланировали выполнение кода с помощью ,
то его выполнение не может быть приостановлено, также как и с обычной функцией. Обратитесь к
, чтобы лучше понять
работу .

«Бесконечный цикл» Выполнение ~

Если у вас есть код, который нужно выполнить несколько раз, то можно использовать
для этого . принимает параметром функцию, которая будет
выполняться бесконечное количество раз с заданным интервалом в миллисекундах, сам интервал передается
вторым параметром. Как и в случае с можно передавать дополнительные аргументы,
эти аргументы будут переданы функции при вызове. Также как и с , задержка не может
быть гарантирована из-за операций, которые могут удерживать цикл событий, следовательно, нужно
рассматривать эту задержку как приблизительную. Смотрите пример ниже:

В примере выше будет выполняться каждые 1500 миллисекунд
или 1.5 секунд, до тех пор, пока ее не остановят (см. ниже).

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

Потеря this

Одной из проблем
использования setTimeout и setInterval является потеря
this при вызове
методов объектов. Например:

let car = {
    model "bmw",
 
    showModel() {
         console.log( this.model );
    }
};
 
setTimeout(car.showModel, 1000);

В консоле мы увидим undefined. Почему? Дело в том, что здесь теряется контекст
при вызове функции. Это эквивалентно вот такому вызову:

let show = car.showModel;
show();

И, так как в JavaScript this вычисляется
динамически при каждом вызове функции, то здесь JavaScript-машина просто
не может связать функцию show с объектом car.

Исправить
ситуацию можно несколькими способами. Первый:

setTimeout(function() {car.showModel();}, 1000);

вызвать car.showModel
через анонимную функцию-обертку. Здесь мы при вызове явно указываем объект car, поэтому this будет определен
корректно. Второй способ – использовать метод bind, о котором мы
говорили на предыдущем занятии:

let show = car.showModel.bind(car);
setTimeout(show, 1000);

Этот способ
предпочтительнее использовать на практике, так как после вызова bind он не зависит от
значения переменной car. Если она будет изменена, то функция show все равно
корректно вызовется, а вот в первом случае мы бы получили ошибку. Вот это
следует иметь в виду при реализации отложенных вызовов.

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

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

let group = {
    title "ТКбд-11",
    students "Иванов", "Петров", "Сидоров",
 
    showList() { 
         this.students.forEach(
             student => console.log(this.title + ': ' + student)
         );
    }
};
 
group.showList();

Здесь метод forEach при вызове
обычной функции устанавливает контекст this=undefined, но при
использовании стрелочной функции контекст неизбежно берется от функции showList и this=group. Например, если
заменить стрелочную функцию на обычную, то получим ошибку:

function(student) {console.log(this.title + ': ' + student);}

с сообщением undefined не имеет свойства title.

Видео по теме

JavaScipt #1: что это такое, с чего начать, как внедрять и запускать

JavaScipt #2: способы объявления переменных и констант в стандарте ES6+

JavaScript #3: примитивные типы number, string, Infinity, NaN, boolean, null, undefined, Symbol

JavaScript #4: приведение типов, оператор присваивания, функции alert, prompt, confirm

JavaScript #5: арифметические операции: +, -, *, /, **, %, ++, —

JavaScript #6: условные операторы if и switch, сравнение строк, строгое сравнение

JavaScript #7: операторы циклов for, while, do while, операторы break и continue

JavaScript #8: объявление функций по Function Declaration, аргументы по умолчанию

JavaScript #9: функции по Function Expression, анонимные функции, callback-функции

JavaScript #10: анонимные и стрелочные функции, функциональное выражение

JavaScript #11: объекты, цикл for in

JavaScript #12: методы объектов, ключевое слово this

JavaScript #13: клонирование объектов, функции конструкторы

JavaScript #14: массивы (array), методы push, pop, shift, unshift, многомерные массивы

JavaScript #15: методы массивов: splice, slice, indexOf, find, filter, forEach, sort, split, join

JavaScript #16: числовые методы toString, floor, ceil, round, random, parseInt и другие

JavaScript #17: методы строк — length, toLowerCase, indexOf, includes, startsWith, slice, substring

JavaScript #18: коллекции Map и Set

JavaScript #19: деструктурирующее присваивание

JavaScript #20: рекурсивные функции, остаточные аргументы, оператор расширения

JavaScript #21: замыкания, лексическое окружение, вложенные функции

JavaScript #22: свойства name, length и методы call, apply, bind функций

JavaScript #23: создание функций (new Function), функции setTimeout, setInterval и clearInterval

Рекурсивный setTimeout

Есть два способа запускать что-то регулярно.

Один из них . Другим является рекурсивный . Например:

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

Рекурсивный – более гибкий метод, чем . С его помощью последующий вызов может быть задан по-разному в зависимости от результатов предыдущего.

Например, необходимо написать сервис, который отправляет запрос для получения данных на сервер каждые 5 секунд, но если сервер перегружен, то необходимо увеличить интервал запросов до 10, 20, 40 секунд…
Вот псевдокод:

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

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

Сравним два фрагмента кода. Первый использует :

Второй использует рекурсивный :

Для внутренний планировщик будет выполнять каждые 100 мс:

Обратили внимание?

Реальная задержка между вызовами с помощью меньше, чем указано в коде!

Это нормально, потому что время, затраченное на выполнение , использует часть заданного интервала времени.

Вполне возможно, что выполнение будет дольше, чем мы ожидали, и займёт более 100 мс.

В данном случае движок ждёт окончания выполнения и затем проверяет планировщик и, если время истекло, немедленно запускает его снова.

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

Ниже представлено изображение, показывающее процесс работы рекурсивного :

Рекурсивный гарантирует фиксированную задержку (здесь 100 мс).

Это потому, что новый вызов планируется в конце предыдущего.

Сборка мусора и колбэк setTimeout/setInterval

Когда функция передаётся в , на неё создаётся внутренняя ссылка и сохраняется в планировщике. Это предотвращает попадание функции в сборщик мусора, даже если на неё нет других ссылок.

Для функция остаётся в памяти до тех пор, пока не будет вызван .

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

Summary

  • Methods and allow us to run the once/regularly after milliseconds.
  • To cancel the execution, we should call with the value returned by .
  • Nested calls are a more flexible alternative to , allowing us to set the time between executions more precisely.
  • Zero delay scheduling with (the same as ) is used to schedule the call “as soon as possible, but after the current script is complete”.
  • The browser limits the minimal delay for five or more nested calls of or for (after 5th call) to 4ms. That’s for historical reasons.

Please note that all scheduling methods do not guarantee the exact delay.

For example, the in-browser timer may slow down for a lot of reasons:

  • The CPU is overloaded.
  • The browser tab is in the background mode.
  • The laptop is on battery.

All that may increase the minimal timer resolution (the minimal delay) to 300ms or even 1000ms depending on the browser and OS-level performance settings.

setTimeout с нулевой задержкой

Особый вариант использования: или просто .

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

Так вызов функции будет запланирован сразу после выполнения текущего кода.

Например, этот код выводит «Привет» и затем сразу «Мир»:

Первая строка помещает вызов в «календарь» через 0 мс. Но планировщик проверит «календарь» только после того, как текущий код завершится. Поэтому выводится первым, а – после него.

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

Минимальная задержка вложенных таймеров в браузере

В браузере есть ограничение на то, как часто внутренние счётчики могут выполняться. В говорится: «после пяти вложенных таймеров интервал должен составлять не менее четырёх миллисекунд.».

Продемонстрируем в примере ниже, что это означает. Вызов повторно вызывает себя через 0 мс. Каждый вызов запоминает реальное время от предыдущего вызова в массиве . Какова реальная задержка? Посмотрим:

Первый таймер запускается сразу (как и указано в спецификации), а затем задержка вступает в игру, и мы видим .

Аналогичное происходит при использовании вместо : запускает несколько раз с нулевой задержкой, а затем с задержкой 4+ мс.

Это ограничение существует давно, многие скрипты полагаются на него, поэтому оно сохраняется по историческим причинам.

Этого ограничения нет в серверном JavaScript. Там есть и другие способы планирования асинхронных задач. Например, setImmediate для Node.js. Так что это ограничение относится только к браузерам.

대기 시간이 0인 setTimeout

이나 을 사용하면 의 대기 시간을 0으로 설정할 수 있습니다.

이렇게 대기 시간을 0으로 설정하면 을 ‘가능한 한’ 빨리 실행할 수 있습니다. 다만, 이때 스케줄러는 현재 실행 중인 스크립트의 처리가 종료된 이후에 스케줄링한 함수를 실행합니다.

이런 특징을 이용하면 현재 스크립트의 실행이 종료된 ‘직후에’ 원하는 함수가 실행될 수 있게 할 수 있습니다.

예시를 실행하면 얼럿창에 ‘Hello’와 ‘World’가 순서대로 출력되는 것을 확인할 수 있습니다.

예시에서 첫 번째 줄은 ‘0밀리초 후에 함수 호출하기’라는 할 일을 ‘계획표에 기록’해주는 역할을 합니다. 그런데 스케줄러는 현재 스크립트(alert 함수)의 실행이 종료되고 나서야 ‘계획표에 어떤 할 일이 적혀있는지 확인’하므로, 가 먼저, 은 그다음에 출력됩니다.

대기 시간이 0인 setTimeout을 활용한 브라우저 환경에서의 유스 케이스는 이벤트 루프와 매크로·마이크로태스크에서 자세히 다루도록 하겠습니다.

브라우저 환경에서 실제 대기 시간은 0이 아닙니다.

브라우저는 에서 정한 중첩 타이머 실행 간격 관련 제약을 준수합니다. 해당 표준엔 «다섯 번째 중첩 타이머 이후엔 대기 시간을 최소 4밀리초 이상으로 강제해야 한다.»라는 제약이 명시되어있습니다.

예시를 보며 이 제약 사항을 이해해봅시다. 예시 내 은 지연 없이 함수 run을 다시 호출할 수 있게 스케줄링 되어 있습니다. 배열 에는 실제 지연 간격에 대한 정보가 기록되도록 해놓았는데, 배열 times에 어떤 값이 저장되는지 알아봅시다.

앞쪽 타이머들은 스펙에 적힌 것처럼 지연 없이 바로 실행됩니다. 그런데 다섯 번째 중첩 타이머 이후엔 지연 간격이 4밀리초 이상이 되어 와 같은 값이 저장되는 것을 확인할 수 있습니다.

이런 제약은 뿐만 아니라 에도 적용됩니다. 도 처음 몇 번은 함수 를 지연 없이 실행하지만, 나중엔 지연 간격을 4밀리초 이상으로 늘려버립니다.

이는 오래전부터 있던 제약인데, 구식 스크립트 중 일부는 아직 이 제약에 의존하는 경우가 있어서 명세서를 변경하지 못하고 있는 상황입니다.

한편, 서버 측엔 이런 제약이 없습니다. Node.js의 process.nextTick과 setImmediate를 이용하면 비동기 작업을 지연 없이 실행할 수 있습니다. 위에서 언급된 제약은 브라우저에 한정됩니다.

setTimeout и setInterval

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

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

Синтаксис и :

// setTimeout
window.setTimeout(func  );
// setInterval
window.setTimeout(func  );

Параметры:

  • – функция, которую нужно вызвать спустя указанное в количество миллисекунд;
  • – количество миллисекунд по истечении которых нужно выполнить ;
  • – дополнительные аргументы, которые нужно передать в .

Например, вызовем функцию один раз по прошествии 3 секунд:

// функция
function myFunc() {
  console.log('after 3 seconds');
}

// вызовем функцию myFunc после 3 секунд
window.setTimeout(myFunc, 3000);
// выведем сообщение в консоль
console.log('immediately');

При выполнение этого кода программа не остановится на месте, где мы зарегистрировали некоторую асинхронность посредством и не будет блокировать её дальнейшее выполнение на 3 секунды, через которые нужно будет вызвать . Выполнение скрипта продолжится дальше и сначала браузер выведет в консоль сообщение «immediately», а затем через 3 секунды – «after 3 seconds».

Другими словами, когда браузер доходит до исполнения , он как бы помещает функцию в некоторое место, а затем по прошествии определённого количества времени её вызывает. При этом блокировка основного потока выполнения программы не происходит.

Чтобы более подробно разобраться в этом необходимо рассмотреть, как движок JavaScript выполняет синхронный и асинхронный код, а также что такое event loop и как он работает.

Синхронный и асинхронный код

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

Выполнение такого кода движок JavaScript выполняет последовательно (т.е. строчку за строчкой). При этом перед тем, как выполнить какую-то строчку кода интерпретатор сначала помещает её в стек вызовов (call stack). Именно в нём происходит её разбор и исполнение. После этого происходит её извлечение из стека и переход к следующей строчке.

Но всё меняется, когда интерпретатор доходит до выполнения асинхронных операций, например . Они также как и синхронные операции сначала попадают в стек вызовов, где происходит их разбор. Но, при разборе интерпретатор понимает, что это некоторый вызов Web API и помещает эту операцию в него. После этого он удаляет эту строчку из call stack и переходит к выполнению следующей строчки кода.

В это же время Web API регистрирует эту функцию и запускает таймер. Как только он завершается, он помещает эту функцию в очередь (callback queue). Очередь – это структура данных типа FIFO. Она хранит все функции в том порядке, в котором они были туда добавлены.

Очередь обратных вызовов (callback queue) обрабатывает цикл событий (event loop). Он смотрит на эту очередь и на стек вызовов (call stack). Если стек вызовов пуст, а очередь нет – то он берёт первую функцию из очереди и закидывает её в стек вызовов, в котором она уже выполняется. Вот таким образом происходит выполнения асинхронного кода в JavaScript.

Если функцию необходимо вызывать не один раз, а постоянно через каждые 3 секунды, то тогда вместо следует использовать :

window.setInterval(myFunc, 3000);

Пример, с передачей функции аргументов:

function sayHello(name) {
  alert(`Привет, ${name}!`);
}
setTimeout(sayHello, 3000, 'Василий'); // Привет, Василий!

Пример, с использованием в анонимной функции:

setTimeout(function (name) {
  alert(`Привет, ${name}!`);
}, 3000, 'Василий');

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

Если функция по каким-то причинам не работает, то проверьте действительно ли вы передаёте ссылку на функцию, а неё результат:

function sayHello() {
  console.log('Привет!');
}

// передаём в setTimeout не ссылку на функцию sayHello, а результат её вызова
setTimeout(sayHello(), 3000);

Tekrarlı setTimeout

Bir kodu düzenli olarak çalıştırmanın iki yolu bulunmaktadır.

İlki diğeri ise aşağıdaki gibi kullanılan :

bir sonraki çağrıyı o anki çağrı bittiği ana planlar

Kendini tekrar eden ‘den daha esnektir. Bu şekliyle kullanıldığında bir sonraki planlanan çağrı ana çağrının durumuna göre ötelebilir veya daha geriye alınabilir.

Örneğin, her 5 sn’de bir sunucudan veri isteyen bir servis yazmamız gerekmektedir. Fakat sunucuya fazladan yük binerse bunun 10,20,40 sn olarak değiştirilmesi gerekmektedir.

Sözde kod aşağıdaki gibidir:

Eğer CPU-aç görevleriniz varsa bu görevlerin süresini ölçüp buna göre bir çalışma planı oluşturmak mümkündür.

Kendini tekrar eden iki çağrı arasındaki süreyi garanti eder fkat bunu garanti etmez.

Aşağıdaki iki kod parçacığı karşılaştırılacak olursa:

İkincisi tekrarlı kullanmaktadır.

fonksiyonunu her 100ms’de bir çalıştırır.

Dikkatinizi çekti mi?…

çağrıları arasındaki geçen süre koddan daha kısa.

Doğal olan bu aslında çünkü çalıştığında bu arlığın bir kısmını harcar.

Hatta bu çalışmasının bizim beklediğimiz ‘den fazla olması da mümkündür.

Bu durumda JS Motoru fonksiyonunun bitmesini bekler, sonra planlayıcıyı kontrol eder eğer zaman geçmişse hiç beklemeden tekrar çalıştırır.

Bu durumda ile karşılaşıldığında fonksiyon hiç beklemeden sürekli çalışır.

Aşağıda ise kendini çağıran gösterilmiştir:

Kendini çağıran arada geçen sürenin aynı olmasını garanti eder.(burada 100ms).

Bunun nedeni yeni çağrının önceki çağrının bitiminde hesaplanmasından dolayıdır.

Garbage collection

Bir fonksiyon ‘a gönderildiğinde içeride bir referansını oluşturup zamanlayıcıya kaydeder. Bundan dolayı bu fonksiyon Çöp toplama işlemine girmez. Dışarıda hiç bir referans olmasa bile bu fonksiyon yok olmaz.

metodu için fonksiyon çağırılmadığı sürece hafızada kalır.

Bunun yan etkisi ise, dışarıdaki fonksiyondan veri almak isteyen bir fonksiyon sürekli çağırılır ve ayakta kalırsa dışarıdaki değişkenlerin de sürekliliği devam eder. Asıl bu fonksiyonun kendisinden bile fazla hafıza kaplayabilir. Öyleyse zamanlayıcı ile işiniz bittiğinde en iyisi iptal etmektir. Bu fonksiyonunuz küçük olsa bile yapılması gereken bir işlemdir.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector