Setinterval
Содержание:
Using Arrow Functions with setTimeout
Arrow functions were introduced with ES6. They have a much shorter syntax than a regular function:
You can, of course, use them with , but there’s one gotcha to be aware of — namely, that arrow functions don’t have their own value. Instead, they use the value of the enclosing lexical context.
Using a regular function:
Using an arrow function:
In the second example, points to the global object (which again, doesn’t have a property).
This can trip us up when using arrow functions with . Previously we saw how we can supply a function called in a with the correct value:
This won’t work when using an arrow function in the method, as the arrow function doesn’t have its own value. The method will still log .
Cleaner Code with Arrow Functions and setTimeout
However, because arrow functions don’t have their own value, it can also work to our advantage.
Consider code like this:
It can be rewritten more concisely with an arrow function:
If you’d like a primer on arrow functions, please read “ES6 Arrow Functions: Fat and Concise Syntax in JavaScript”.
Рекурсивный setTimeout
Есть два способа запускать что-то регулярно.
Один из них . Другим является рекурсивный . Например:
Метод выше планирует следующий вызов прямо после окончания текущего .
Рекурсивный – более гибкий метод, чем . С его помощью последующий вызов может быть задан по-разному в зависимости от результатов предыдущего.
Например, необходимо написать сервис, который отправляет запрос для получения данных на сервер каждые 5 секунд, но если сервер перегружен, то необходимо увеличить интервал запросов до 10, 20, 40 секунд…
Вот псевдокод:
А если функции, которые мы планируем, ресурсоёмкие и требуют времени, то мы можем измерить время, затраченное на выполнение, и спланировать следующий вызов раньше или позже.
Рекурсивный позволяет задать задержку между выполнениями более точно, чем .
Сравним два фрагмента кода. Первый использует :
Второй использует рекурсивный :
Для внутренний планировщик будет выполнять каждые 100 мс:
Обратили внимание?
Реальная задержка между вызовами с помощью меньше, чем указано в коде!
Это нормально, потому что время, затраченное на выполнение , использует часть заданного интервала времени.
Вполне возможно, что выполнение будет дольше, чем мы ожидали, и займёт более 100 мс.
В данном случае движок ждёт окончания выполнения и затем проверяет планировщик и, если время истекло, немедленно запускает его снова.
В крайнем случае, если функция всегда выполняется дольше, чем задержка , то вызовы будут выполняться без задержек вообще.
Ниже представлено изображение, показывающее процесс работы рекурсивного :
Рекурсивный гарантирует фиксированную задержку (здесь 100 мс).
Это потому, что новый вызов планируется в конце предыдущего.
Сборка мусора и колбэк setTimeout/setInterval
Когда функция передаётся в , на неё создаётся внутренняя ссылка и сохраняется в планировщике. Это предотвращает попадание функции в сборщик мусора, даже если на неё нет других ссылок.
Для функция остаётся в памяти до тех пор, пока не будет вызван .
Есть и побочный эффект. Функция ссылается на внешнее лексическое окружение, поэтому пока она существует, внешние переменные существуют тоже. Они могут занимать больше памяти, чем сама функция. Поэтому, если регулярный вызов функции больше не нужен, то лучше отменить его, даже если функция очень маленькая.
중첩 setTimeout
무언가를 일정 간격을 두고 실행하는 방법에는 크게 2가지가 있습니다.
하나는 을 이용하는 방법이고, 다른 하나는 아래 예시와 같이 중첩 을 이용하는 방법입니다.
다섯 번째 줄의 은 로 표시한 줄의 실행이 종료되면 다음 호출을 스케줄링합니다.
중첩 을 이용하는 방법은 을 사용하는 방법보다 유연합니다. 호출 결과에 따라 다음 호출을 원하는 방식으로 조정해 스케줄링 할 수 있기 때문입니다.
5초 간격으로 서버에 요청을 보내 데이터를 얻는다고 가정해 봅시다. 서버가 과부하 상태라면 요청 간격을 10초, 20초, 40초 등으로 증가시켜주는 게 좋을 겁니다.
아래는 이를 구현한 의사 코드입니다.
CPU 소모가 많은 작업을 주기적으로 실행하는 경우에도 을 재귀 실행하는 방법이 유용합니다. 작업에 걸리는 시간에 따라 다음 작업을 유동적으로 계획할 수 있기 때문입니다.
중첩 을 이용하는 방법은 지연 간격을 보장하지만 은 이를 보장하지 않습니다.
아래 두 예시를 비교해 봅시다. 첫 번째 예시에선 을 이용했습니다.
두 번째 예시에선 중첩 을 이용했습니다.
첫 번째 예시에선, 내부 스케줄러가 를 100밀리초마다 실행합니다.
그림을 보고 뭔가 알아차리셨나요?
을 사용하면 호출 사이의 지연 간격이 실제 명시한 간격(100ms)보다 짧아집니다!
이는 을 실행하는 데 ‘소모되는’ 시간도 지연 간격에 포함시키기 때문입니다. 지극히 정상적인 동작이죠.
그렇다면 을 실행하는 데 걸리는 시간이 명시한 지연 간격보다 길 때 어떤 일이 발생할까요?
이런 경우는 엔진이 의 실행이 종료될 때까지 기다려줍니다. 의 실행이 종료되면 엔진은 스케줄러를 확인하고, 지연 시간이 지났으면 다음 호출을 바로 시작합니다.
따라서 함수 호출에 걸리는 시간이 매번 밀리초보다 길면, 모든 함수가 쉼 없이 계속 연속 호출됩니다.
한편, 중첩 을 이용하면 다음과 같이 실행 흐름이 이어집니다.
중첩 을 사용하면 명시한 지연(여기서는 100ms)이 보장됩니다.
이렇게 지연 간격이 보장되는 이유는 이전 함수의 실행이 종료된 이후에 다음 함수 호출에 대한 계획이 세워지기 때문입니다.
가비지 컬렉션과 setInterval·setTimeout
이나 에 함수를 넘기면, 함수에 대한 내부 참조가 새롭게 만들어지고 이 참조 정보는 스케줄러에 저장됩니다. 따라서 해당 함수를 참조하는 것이 없어도 과 에 넘긴 함수는 가비지 컬렉션의 대상이 되지 않습니다.
의 경우는, 이 호출되기 전까지 함수에 대한 참조가 메모리에 유지됩니다.
그런데 이런 동작 방식에는 부작용이 하나 있습니다. 외부 렉시컬 환경을 참조하는 함수가 있다고 가정해 봅시다. 이 함수가 메모리에 남아있는 동안엔 외부 변수 역시 메모리에 남아있기 마련입니다. 그런데 이렇게 되면 실제 함수가 차지했어야 하는 공간보다 더 많은 메모리 공간이 사용됩니다. 이런 부작용을 방지하고 싶다면 스케줄링할 필요가 없어진 함수는 아무리 작더라도 취소하도록 합시다.
setInterval()
Эта функция, как и предполагается из названия, в основном используется для задержки функций, которые будут выполняться снова и снова, например анимации. Функция очень близка к , у них даже такой же синтаксис:
setInterval ( expression, interval );
Но разница тут вот в чём. запускает только единожды, в то время, как продолжает запускать на регулярной основе после заданного временного интервала, пока вы не скажете стоп.
Для того, чтобы остановить последующие вызовы в , вам нужно вызывать , где это имя функции .
// Hello показывается каждые 3 секундыlet timerId= setInterval(() => alert('Hello'), 3000);// Повторения прекращаются после 6 секунд с id таймера.setTimeout(() => { clearInterval(timerId); alert('Bye'); }, 6000);
Когда вам нужно использовать ? Когда вам не нужно вызывать в конце спланированной функции. Также, во время использования , фактически не существует задержки между одним срабатыванием настоящего выражения и последующим. А в существует относительно долгая задержка, во время выполнения выражения, вызова функции и выставления нового . Так что если вам нужен обычный точный таймер и надо, чтобы что-то делалось повторно после определенного временного интервала, тогда это ваш выбор.Итак, сейчас мы подобрались к самому интересному. А именно к . А про него нужно рассказать максимально подробно.
requestAnimationFrame()
Если вы используете анимации в своих веб-приложениях, то вы в любом случае хотите, чтобы они выполнялись как по маслу. И самым простым способом для этого является использование , ну или просто — метода который делает это непринужденно и легко.
Использование этого метода позволяет браузеру справиться с некоторыми затруднительными задачами связанными с анимацией, например такими как управление частотой кадров.
До этого разработчики использовали и , чтобы создавать анимации. Проблема тут была в том, что для того, чтобы анимации были плавными, браузер зачастую отрисовывал кадры быстрее, чем они могут показаться на экране. Что вело к ненужным вычислениям. Также ещё одной проблемой в использовании или было то, что эти анимации продолжали работать, даже если страница не находилась в поле видимости пользователя.
More Examples
Example
You can also refer to a «named» function; Alert «Hello» every 3 seconds (3000 milliseconds):
var myVar;function myFunction() { myVar = setInterval(alertFunc, 3000);}function alertFunc() { alert(«Hello!»);}
Example
Display the current time (the setInterval() method will execute the function
once every 1 second, just like a digital watch):
var myVar = setInterval(myTimer, 1000);function myTimer()
{ var d = new Date(); var t = d.toLocaleTimeString();
document.getElementById(«demo»).innerHTML = t;}
Example
Using clearInterval() to stop time in the previous example:
var myVar = setInterval(myTimer, 1000);function myTimer()
{ var d = new Date(); var t = d.toLocaleTimeString();
document.getElementById(«demo»).innerHTML = t;}function myStopFunction()
{ clearInterval(myVar);}
Example
Using setInterval() and clearInterval() to create a dynamic progress bar:
function move() { var elem = document.getElementById(«myBar»); var width = 0; var id = setInterval(frame, 10); function frame() { if (width == 100) { clearInterval(id); } else { width++; elem.style.width = width + ‘%’;
} }}
Example
Toggle between two background colors once every 300 milliseconds:
var myVar = setInterval(setColor, 300);function setColor() { var x = document.body; x.style.backgroundColor = x.style.backgroundColor == «yellow» ? «pink» : «yellow»;}
function stopColor() { clearInterval(myVar);}
Example
Pass parameters to the alertFunc function (does not work in IE9 and earlier):
var myVar;function myStartFunction() { myVar = setInterval(alertFunc, 2000, «First param», «Second param»);}
However, if you use an anonymous function, it will work in
all browsers:
var myVar;function myStartFunction() { myVar = setInterval(function(){ alertFunc(«First param», «Second param»); }, 2000);
}
setTimeout
Yazımı:
Parametreler:
- Fonksiyon veya çalıştırılacak kodun karakter dizisi hali. Genelde bu fonksiyon olur. Uyumluluk dolayısıyla karakter dizisi de gönderilebilir fakat önerilmez.
- Milisaniye cinsiden çalışmadan önceki bekleme süresi.(1000 ms = 1 saniye).
- , …
- Fonksiyon için gerekli argümanlar.( IE9 öncesinde çalışmaz.)
Örneğin aşağıdaki kod fonksiyonunu bir saniye sonra çalıştırır:
Argümanlı versiyonu:
Eğer ilk argüman karakter dizisi ise, sonrasında JavaScript bundan fonksiyon üretir.
Aşağıdaki de aynı şekilde çalışacaktır:
Karakter dizisi olarak fonksiyon göndermek aslında pek önerilmez, bunun yerine aşağıdaki gibi fonksiyon kullanılması daha doğrudur:
Fonksiyon gönder fakat çalıştırma.
Yeni başlayan arkadaşlar bazen yanlışlıkla fonksiyonun sonuna ekleyebilir:
Bu çalışmaz, çünkü referans bir fonksiyon beklemektedir. Burada derseniz fonksiyonu çalıştırırsınız ve bunun sonucu fonksiyonu tarafından kullanılır. Bizim durumumuzda döndürür. ( fonksiyon ile alakalı bir sorun yok ) bundan dolayı hiç birşey zamanlanmaz.
çağrısı “timer identifier” döner. Bu ile zamanlayıcıyı iptal edebiliriz.
Yazımı aşağıdaki gibidir:
Aşağıdaki kodda önce bir zamanlayıcı test eder sonrasında ise bunu iptal eder. Sonuç olarak hiçbir şey olmaz:
çıktısından da göreceğiniz gibi timer bir id numarası ile tanımlanır. Diğer ortamlarda bu başka birşey olabilir. Örneğin Node.Js bir sayı yerine farklı metodları olan timer objesi döner.
Tekrar söylemek gerekirse üzerinde anlaşılmış bir şartname bulunmamaktadır.
Tarayıcılar için zamanlayıcılar belirtilmiştir.
Управление временным континуумом с 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(…,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
- İlk çalışma: .
- ikinci çalışma:
- … 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.
Nested setTimeout
There are two ways of running something regularly.
One is . The other one is a nested , like this:
The above schedules the next call right at the end of the current one .
The nested is a more flexible method than . This way the next call may be scheduled differently, depending on the results of the current one.
For instance, we need to write a service that sends a request to the server every 5 seconds asking for data, but in case the server is overloaded, it should increase the interval to 10, 20, 40 seconds…
Here’s the pseudocode:
And if the functions that we’re scheduling are CPU-hungry, then we can measure the time taken by the execution and plan the next call sooner or later.
Nested allows to set the delay between the executions more precisely than .
Let’s compare two code fragments. The first one uses :
The second one uses nested :
For the internal scheduler will run every 100ms:
Did you notice?
The real delay between calls for is less than in the code!
That’s normal, because the time taken by ‘s execution “consumes” a part of the interval.
It is possible that ‘s execution turns out to be longer than we expected and takes more than 100ms.
In this case the engine waits for to complete, then checks the scheduler and if the time is up, runs it again immediately.
In the edge case, if the function always executes longer than ms, then the calls will happen without a pause at all.
And here is the picture for the nested :
The nested guarantees the fixed delay (here 100ms).
That’s because a new call is planned at the end of the previous one.
Garbage collection and setInterval/setTimeout callback
When a function is passed in , an internal reference is created to it and saved in the scheduler. It prevents the function from being garbage collected, even if there are no other references to it.
For the function stays in memory until is called.
There’s a side-effect. A function references the outer lexical environment, so, while it lives, outer variables live too. They may take much more memory than the function itself. So when we don’t need the scheduled function anymore, it’s better to cancel it, even if it’s very small.