Вернуться к уроку

Что выведет после setInterval?

важность: 5

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

После этого запущена тяжёлая функция f, выполнение которой (мы точно знаем) потребует более 100 мс.

Сработает ли setInterval, как и когда?

Варианты:

  1. Да, несколько раз, в процессе выполнения f.
  2. Да, несколько раз, сразу после выполнения f.
  3. Да, один раз, сразу после выполнения f.
  4. Нет, не сработает.
  5. Может быть по-разному, как повезёт.

Что выведет alert в строке (*)?

var i;
var timer = setInterval(function() { // планируем setInterval каждые 10 мс
  i++;
}, 10);

setTimeout(function() { // через 50 мс - отмена setInterval
  clearInterval(timer);
  alert( i ); // (*)
}, 50);

// и запускаем тяжёлую функцию
function f() {
  // точное время выполнения не играет роли
  // здесь оно заведомо больше 100 мс
  for (i = 0; i < 1e8; i++) f[i % 2] = i;
}

f();

Вызов alert(i) в setTimeout введет 100000001.

Можете проверить это запуском:

var timer = setInterval(function() {
  i++;
}, 10);

setTimeout(function() {
  clearInterval(timer);
  alert( i ); // (*)
}, 50);

var i;

function f() {
  // точное время выполнения не играет роли
  // здесь оно заведомо больше 100 мс
  for (i = 0; i < 1e8; i++) f[i % 2] = i;
}

f();

Правильный вариант срабатывания: 3 (сразу же по окончании f один раз).

Планирование setInterval будет вызывать функцию каждые 10 мс после текущего времени. Но так как интерпретатор занят долгой функцией, то до конца ее работы никакого вызова не происходит.

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

После окончания текущего скрипта интерпретатор обращается к очереди запланированных вызовов, видит в ней setInterval и выполняет. А затем тут же выполняется setTimeout, очередь которого тут же подошла.

Итого, как раз и видим, что setInterval выполнился ровно 1 раз по окончании работы функции. Такое поведение кросс-браузерно.