Главная » Отношения » Javascript запретить одновременный запуск нескольких таймеров setinterval. Примеры jQuery-функции setTimeout(). Минимальная задержка таймера

Javascript запретить одновременный запуск нескольких таймеров setinterval. Примеры jQuery-функции setTimeout(). Минимальная задержка таймера

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

  • var id = setTimeout(fn, delay); - Создает простой таймер, который вызовет заданную функцию после заданной задержки. Функция возвращает уникальный ID, с помощью которого таймер может быть приостановлен.
  • var id = setInterval(fn, delay); - Похоже на setTimeout, но непрерывно вызывает функцию с заданным интервалом (пока не будет остановлена).
  • clearInterval(id);, clearTimeout(id); - Принимает таймер ID (возвращаемый одной из функций, описанных выше) и останавливает выполнение callback"a.
Главная идея, которую нужно рассмотреть, заключается в том, что точность периода задержки таймера не гарантируется. Начнем с того, что браузер исполняет все асинхронные JavaScript-события в одном потоке (такие как клик мышью или таймеры) и только в то время, когда пришла очередь этого события. Лучше всего это демонстрирует следующая диаграмма:

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

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

Для начала представим, что внутри JavaScript блока стартуют два таймера: setTimeout с задержкой 10мс и setInterval с такой же задержкой. В зависимости от того, когда стартует таймер, он сработает в момент, когда мы еще не завершили первый блок кода. Заметьте, однако, что он не срабатывает сразу (это невозможно из-за однопоточности). Вместо этого отложенная функция попадает в очередь и исполняется в следующий доступный момент.

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

После того, как первый блок JavaScript кода был выполнен, браузер задается вопросом «Что ожидает исполнения?». В данном случае обработчик клика мышью и таймер находятся в состоянии ожидания. Браузер выбирает один из них (обработчик клика) и выполняет его. Таймер будет ожидать следующей доступной порции времени в очереди на исполнение.

Заметьте, что пока обработчик клика мышью выполняется, срабатывает первый interval-callback. Так же как и timer-callback, он будет поставлен в очередь. Тем не менее, учтите, что когда снова сработает interval (пока будет выполняться timer-callback), то он будет удален из очереди. Если бы все interval-callback"и попадали в очередь пока исполняется большой кусок кода, это бы привело к тому, что образовалась бы куча функций, ожидающих вызова без периодов задержек между окончанием их выполнения. Вместо этого браузеры стремятся ждать пока не останется ни одной функции в очереди прежде чем добавить в очередь еще одну.

Таким образом, мы можем наблюдать случай, когда третье срабатывание interval-callback совпадает с тем моментом, когда он уже исполняется. Это иллюстрирует важную особенность: интервалы не заботятся о том, что выполняется в текущий момент, они будут добавлены в очередь без учета периода задержки между исполнениями.

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

Давайте рассмотрим пример, который хорошо иллюстрирует разницу между setTimeout и setInterval.
setTimeout(function(){ /* Some long block of code... */ setTimeout(arguments.callee, 10); }, 10); setInterval(function(){ /* Some long block of code... */ }, 10);
Эти два варианта эквивалентны на первый взгляд, но на самом деле это не так. Код, использующий setTimeout будет всегда иметь задержку хотя бы 10мс после предыдущего вызова (он может быть больше, но никогда не может быть меньше), тогда как код, использующий setInterval будет стремиться вызываться каждые 10мс независимо от того, когда отработал предыущий вызов.

Давайте резюмируем все сказанное выше:
- JavaScript движки используют однопоточную среду, преобразовывая асинхронные события в очередь, ожидающую исполнения,
- Функции setTimeout и setInterval принципиально по-разному исполняются в асинхронном коде,
- Если таймер не может быть выполнен в данный момент, он будет отложен до следующей точки исполнения (которая будет дольше, чем желаемая задержка),
- Интервалы (setInterval) могут исполняться друг за другом без задержек, если их исполнение занимает больше времени, чем указанная задержка.

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

Источник: http://learn.javascript.ru/settimeout-setinterval

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

В частности, эта возможность поддерживается в браузерах и в сервере Node.JS.

setTimeout

Синтаксис:

var timerId = setTimeout(func/code, delay[, arg1, arg2...])

Параметры:

  • func/code
    • Функция или строка кода для исполнения.
    • Строка поддерживается для совместимости, использовать её не рекомендуется.
  • delay
    • Задержка в милисекундах, 1000 милисекунд равны 1 секунде.
  • arg1, arg2…
    • Аргументы, которые нужно передать функции. Не поддерживаются в IE9-.
    • Исполнение функции произойдёт спустя время, указанное в параметре delay .

Например, следующий код вызовет alert("Привет") через одну секунду:

function func () { alert("Привет" ); } setTimeout(func, 1000 );

Если первый аргумент является строкой, то интерпретатор создаёт анонимную функцию из этой строки.

То есть такая запись работает точно так же:

SetTimeout("alert("Привет")" , 1000 );

Вместо них используйте анонимные функции:

SetTimeout(function () { alert("Привет" ) }, 1000 );

Параметры для функции и контекст

Во всех современных браузерах, с учетом IE10, setTimeout позволяет указать параметры функции.

Пример ниже выведет "Привет, я Вася" везде, кроме IE9-:

function sayHi (who) { alert("Привет, я " + who); } setTimeout(sayHi, 1000 , "Вася" );

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

function sayHi (who) { alert("Привет, я " + who); } setTimeout(function () { sayHi("Вася" ) }, 1000 );

Вызов через setTimeout не передаёт контекст this .

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

Например, вызовем user.sayHi() через одну секунду:

function User (id) function () { alert(this .id); }; } var user = new User(12345 ); setTimeout(user.sayHi, 1000 ); // ожидается 12345, но выведет "undefined"

Так как setTimeout запустит функцию user.sayHi в глобальном контексте, она не будет иметь доступ к объекту через this .

Иначе говоря, эти два вызова setTimeout делают одно и то же:

// (1) одна строка setTimeout(user.sayHi, 1000 ); // (2) то же самое в две строки var func = user.sayHi; setTimeout(func, 1000 );

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

function User (id) { this .id = id; this .sayHi = function () { alert(this .id); }; } var user = new User(12345 ); setTimeout(function () { user.sayHi(); }, 1000 );

Функция-обёртка используется, чтобы кросс-браузерно передать аргументы и сохранить контекст выполнения.

Отмена исполнения

Функция setTimeout возвращает идентификатор timerId , который можно использовать для отмены действия.

Синтаксис:

ClearTimeout(timerId)

В следующем примере мы ставим таймаут, а затем удаляем (передумали). В результате ничего не происходит.

var timerId = setTimeout(function () { alert(1 ) }, 1000 ); clearTimeout(timerId);

setInterval

Метод setInterval имеет синтаксис, аналогичный setTimeout .

var timerId = setInterval(func/code, delay[, arg1, arg2...])

Смысл аргументов — тот же самый. Но, в отличие от setTimeout , он запускает выполнение функции не один раз, а регулярно повторяет её через указанный интервал времени. Остановить исполнение можно вызовом:

ClearInterval(timerId)

Следующий пример при запуске станет выводить сообщение каждые две секунды, пока вы не нажмете на кнопку «Стоп»:

<input type ="button" onclick ="clearInterval(timer)" value ="Стоп" > <script > var i = 1 ; var timer = setInterval(function () { alert(i++) }, 2000 ); script >

Очередь и наложение вызовов в setInterval

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

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

Для примера, возьмем setInterval(function() { func(i++) }, 100) . Она выполняет func каждые 100 мс, каждый раз увеличивая значение счетчика.

На картинке ниже, красный блок - это время исполнения func . Время между блоком — это время между запусками функции, и оно меньше, чем установленная задержка!

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

Бывает, что исполнение функции занимает больше времени, чем задержка. Например, функция сложная, а задержка маленькая. Или функция содержит операторы alert / confirm / prompt , которые блокируют поток выполнения. В этом случае начинаются интересные вещи.

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

Изображение ниже иллюстрирует происходящее для функции, которая долго исполняется.

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

Второй запуск функции происходит сразу же после окончания первого:

Больше одного раза в очередь выполнение не ставится.

Если выполнение функции занимает больше времени, чем несколько запланированных исполнений, то в очереди она всё равно будет стоять один раз. Так что «накопления» запусков не происходит.

На изображении ниже setInterval пытается выполнить функцию в 200 мс и ставит вызов в очередь. В 300 мс и 400 мс таймер пробуждается снова, но ничего не просходит.

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

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

Повторение вложенным setTimeout

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

Ниже — пример, который выдает alert с интервалами 2 секунды между ними.

<input type ="button" onclick ="clearTimeout(timer)" value ="Стоп" > <script > var i = 1 ; var timer = setTimeout(function run () { alert(i++); timer = setTimeout(run, 2000 ); }, 2000 ); script >

На временной линии выполнения будут фиксированные задержки между запусками. Иллюстрация для задержки 100мс:

Минимальная задержка таймера

У браузерного таймера есть минимальная возможная задержка. Она меняется от примерно нуля до 4мс в современных браузерах. В более старых она может быть больше и достигать 15мс.

По стандарту, минимальная задержка составляет 4мс. Так что нет разницы между setTimeout(..,1) и setTimeout(..,4) .

В поведении setTimeout и setInterval с нулевой задержкой есть браузерные особенности.

  1. В Opera, setTimeout(.., 0) — то же самое, что setTimeout(.., 4) . Оно выполняется реже, чем setTimeout(.. ,2). Это особенность данного браузера.
  2. В Internet Explorer, нулевая задержка setInterval(.., 0) не сработает. Это касается именно setInterval , т.е. setTimeout(.., 0) работает нормально.

Реальная частота срабатывания

Срабатывание может быть и гораздо реже В ряде случаев задержка может быть не 4мс, а 30мс или даже 1000мс.

Большинство браузеров (десктопных в первую очередь) продолжают выполнять setTimeout / setInterval , даже если вкладка неактивна. При этом ряд из них (Chrome, FF, IE10) снижают минимальную частоту таймера, до 1 раза в секунду. Получается, что в «фоновой» вкладке будет срабатывать таймер, но редко.

При работе от батареи, в ноутбуке — браузеры тоже могут снижать частоту, чтобы реже выполнять код и экономить заряд батареи. Особенно этим известен IE. Снижение может достигать нескольких раз, в зависимости от настроек. При слишком большой загрузке процессора JavaScript может не успевать обрабатывать таймеры вовремя. При этом некоторые запуски setInterval будут пропущены.

Вывод: на частоту 4мс стоит ориентироваться, но не стоит рассчитывать.

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

var timeMark = new Date ; setTimeout(function go () { var diff = new Date - timeMark; // вывести очередную задержку в консоль вместо страницы console .log(diff); // запомним время в самом конце, // чтобы измерить задержку именно между вызовами timeMark = new Date ; setTimeout(go, 100 ); }, 100 );

Трюк setTimeout(func, 0)

Этот трюк достоин войти в анналы JavaScript-хаков.

Функцию оборачивают в setTimeout(func, 0) , если хотят запустить ее после окончания текущего скрипта.

Дело в том, что setTimeout никогда не выполняет функцию сразу. Он лишь планирует ее выполнение. Но интерпретатор JavaScript начнёт выполнять запланированные функции лишь после выполнения текущего скрипта.

По стандарту, setTimeout в любом случае не может выполнить функцию с задержкой 0. Как мы говорили раньше, обычно задержка составит 4мс. Но главное здесь именно то, что выполнение в любом случае будет после выполнения текущего кода.

Например:

var result; function showResult () { alert(result); } setTimeout(showResult, 0 ); result = 2 *2 ; // выведет 4

Итого

Методы setInterval(func, delay) и setTimeout(func, delay) позволяют запускать func регулярно/один раз через delay миллисекунд.

Оба метода возвращают идентификатор таймера. Его используют для остановки выполнения вызовом clearInterval / clearTimeout .

| | setInterval | setTimeout | || ----------- | ---------- | | Тайминг | Идет вызов строго по таймеру. Если интерпретатор занят — один вызов становится в очередь. Время выполнения функции не учитывается, поэтому промежуток времени от окончания одного запуска до начала другого может быть различным. | Рекурсивный вызов setTimeout используется вместо setInterval там, где нужна фиксированная пауза между выполнениями. | | Задержка | Минимальная задержка: 4мс. | Минимальная задержка: 4мс. | | Браузерные особенности | В IE не работает задержка 0. | В Opera нулевая задержка эквивалентна 4мс, остальные задержки обрабатываются точно, в том числе нестандартные 1мс, 2мс и 3мс. |

  • From:
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Topic: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

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

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

var d1 = new Date(), d2 = new Date(); setInterval(function() { var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
"; // Ставим метку в начале функции d1 = new Date(); while (new Date() - d1 < 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

Вывод будет информативным, начиная со второй строчки.

В Firefox, Opera, Safari и Chrome ситуация будет схожая: первое число будет примерно равно 1000, второе - на 200 меньше. Различие будут только в разбросе значений. Самый маленький разброс в Chrome и Opera.

2 Reply by PunBB (edited by PunBB 2017.06.08 16:45)

  • From: Moscow, Sovkhoznay 3, apt. 98
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Ещё одно отличие менее заметное и более трудновоспроизводимое, но иногда способное доставить много хлопот, - это устойчивость к изменению системного времени. Если запустить следующий тест

setInterval(function() { document.body.innerHTML = Math.random(); }, 500);

И после запуска перевести системное время на минуту назад, то в браузерах Firefox и Safari смена чисел приостановится, а через минуту запустится вновь. Конечно, ручной перевод системного времени крайне редкая ситуация, но на многихсистемах настроена автоматическая синхронизация времени с серверами в интернете, поэтому в некоторых ситуациях нельзя сбрасывать со счетов этот фактор.

Ещё один маленький минус функции setInterval - чтобы была возможность остановить её действие, необходимо где-то запоминать её идентификатор, что не всегда удобно.

3 Reply by PunBB

  • From: Moscow, Sovkhoznay 3, apt. 98
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Чтобы избавиться от перечисленных недостатков setInterval можно использовать многократный setTimeout.

Важная альтернатива setInterval – рекурсивный setTimeout:

/** вместо: var timerId = setInterval(function() { alert("тик"); }, 2000); */ var timerId = setTimeout(function tick() { alert("тик"); timerId = setTimeout(tick, 2000); }, 2000);

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

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

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

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

4 Reply by PunBB

  • From: Moscow, Sovkhoznay 3, apt. 98
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Рекурсивный setTimeout гарантирует паузу между вызовами, setInterval – нет.

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

var i = 1; setInterval(function() { func(i); }, 100);

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

var i = 1; setTimeout(function run() { func(i); setTimeout(run, 100); }, 100);

При setInterval внутренний таймер будет срабатывать чётко каждые 100 мс и вызывать func(i):

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

Это естественно, ведь время работы функции никак не учитывается, оно «съедает» часть интервала.

Возможно и такое что func оказалась сложнее, чем мы рассчитывали и выполнялась дольше, чем 100 мс.

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

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

5 Reply by sempai

  • From: Jerusalem
  • Registered: 2015.06.02
  • Posts: 958
  • Likes: 274

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Все зависит от поставленной задачи. Изначально SetTimeOut служит для однократного запуска таймера, а SetInterval для запуска цикла. Но и ту и другую функцию можно использовать для циклической прогонки скриптов, если например запустить рекурсивно в функции SetTimeOut, то она будет действовать практический аналогично SetInterval.

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

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

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

Простой пример setTimeout

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

Посмотреть демо

Синтаксис

В документации MDN приведен следующий синтаксис для setTimeout :

var timeoutID = window.setTimeout(func, ); var timeoutID = window.setTimeout(code, );

  • timeoutID – числовой id , который можно использовать в сочетании с clearTimeout() для отключения таймера;
  • func – функция, которая должна быть выполнена;
  • code (в альтернативном синтаксисе ) – строка кода, которую нужно исполнить;
  • delay – длительность задержки в миллисекундах, после которой будет запущена функция. По умолчанию установлено значение 0.

setTimeout vs window.setTimeout

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

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

Лично я считаю, что это лишь сильно усложняет код. Если бы мы определили альтернативный метод JavaScript timeout , который может быть найден и возвращен в приоритетном порядке, то столкнулись бы с еще большими проблемами.

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

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

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

function explode(){ alert("Boom!"); } setTimeout(explode, 2000);

Переменная, которая обращается к функции:

var explode = function(){ alert("Boom!"); }; setTimeout(explode, 2000);

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

setTimeout(function(){ alert("Boom!"); }, 2000);

  • Такой код плохо воспринимается, а, следовательно, его сложно будет модернизировать или отладить;
  • Он предполагает использование метода eval() , который может стать потенциальной уязвимостью;
  • Этот метод работает медленнее других, так как ему требуется запускать JavaScript-интерпретатор .

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

Передаем параметры в setTimout

В первом (к тому же, кроссбраузерном ) варианте мы передаем параметры в callback-функцию , исполняемую при помощи setTimeout .

В следующем примере мы выделяем случайное приветствие из массива greetings и передаем его в качестве параметра функции greet() , которая исполняется setTimeout с задержкой в 1 секунду:

function greet(greeting){ console.log(greeting); } function getRandom(arr){ return arr; } var greetings = ["Hello", "Bonjour", "Guten Tag"], randomGreeting = getRandom(greetings); setTimeout(function(){ greet(randomGreeting); }, 1000);

Посмотреть демо

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

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

Опираясь на предыдущий пример, мы получаем:

setTimeout(greet, 1000, randomGreeting);

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

Сопутствующие проблемы и “this”

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

var person = { firstName: "Jim", introduce: function(){ console.log("Hi, I"m " + this.firstName); } }; person.introduce(); // Outputs: Hi, I"m Jim setTimeout(person.introduce, 50); // Outputs: Hi, I"m undefined

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

Чтобы избавиться от этой нестыковки, можно воспользоваться несколькими методами:

Принудительно установить значение this

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

setTimeout(person.introduce.bind(person), 50);

Примечание: метод bind был представлен в ECMAScript 5 , а значит, что он будет работать только в современных браузерах. В других при его применении вы получите ошибку выполнения JavaScript «function timeout error » .

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

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

setTimeout($.proxy(person.introduce, person), 50);

Посмотреть демо

Отключение таймера

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

var timer = setTimeout(myFunction, 3000); clearTimeout(timer);

Давайте посмотрим на нее в действии. В следующем примере, если кликнуть по кнопке «Start countdown », начнется обратный отсчет. После того, как он завершится, котята получат свое. Но если нажать кнопку «Stop countdown », таймер JavaScript timeout будет остановлен и сброшен.

Посмотреть пример

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

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



Предыдущая статья: Следующая статья:

© 2015 .
О сайте | Контакты
| Карта сайта