setInterval()

setInterval() в JavaScript — это метод глобального объекта, позволяющий выполнять код или вызывать функцию регулярно с заданным интервалом. Интервальное время задается в миллисекундах, а остановить выполнение кода можно с помощью clearInterval().


Синтаксис

  
  setInterval(() => {
    console.log('Прошло 2 секунды')
  }, 2000)
  

Стоит отметить, что первое сообщение будет выведено в console только через 2 секунды, после начала работы метода, а не немедленно.

Функция в setInterval() может бысть стрелочной, анонимной, именованной, методом объекта или конструктором, а также строкой (что не рекомендуется).

Анонимная

  
  setInterval(function() {
    console.log('Прошло 2 секунды')
  }, 2000)
  

Именованная

  
  setInterval(printMessage, 2000)

  function printMessage() {
      console.log('Прошло 2 секунды')
  }    
  

Записывая имя функции в setInterval() помните, что скобки в данном случае пропускаются.

Задержка

Интервал времени в setInterval() задается в миллисекундах. Если задача - исполнять код каждую секунду, пишем 1000, если каждую минуту - тогда 60000. Можно также установить 0 или даже пропустить этот аргумент. В этом случае метод будет стараться исполнить код как можно чаще, но на практике интервал зависит от ряда факторов, таких как реализация JavaScript и загрузка системы. Если грубо, ориентироваться можно на 4 -10 миллисекунд.

Максимальное же значение, которое можно задать в setInterval() составляет 2147483647 миллисекунд, это около 24.85 дней.

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

  
  setInterval(function() {
    console.log('Прошло 2 секунды')
  }, 2000)
  
  for (let i = 0; i <= 50000; i++) {
    console.log(i)
  }  
  

В данном примере вывод в console сообщения Прошло 2 секунды мы увидим только после того, как отработает цикл for. Хотя интерпретатор зарегистрирует задачу с setInterval() и начнет отсчет, выполнение кода мы не увидим, так как поток будет занят выводом в console чисел от 0 до 50000. После того как работа цикла завершится, мы сразу же увидим работу setInterval().

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

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

  
  setTimeout(print, 2000)

  function print() {
    console.log('Прошло 2 секунды')
    setTimeout(print, 2000)
  }    
  

Дополнительные параметры

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

  
  let startMessage = 'Прошло'
  let endMessage = '2 секунды'
  
  setInterval(printMessage, 2000, startMessage, endMessage)
  
  function printMessage(message1, message2) {
    console.log(`${message1} ${message2}`)
  }    
  

Используя анонимную функцию.

  
  setInterval(function() {
    printMessage(startMessage, endMessage)
  }, 2000)
  

Тоже сработает.

  
  setInterval(function(message1, message2) {
    console.log(`${message1} ${message2}`)
  }, 2000, startMessage, endMessage)
  

Или стрелочную

  
  setInterval(() => printMessage(startMessage, endMessage), 2000)
  

clearInterval

Для того, чтобы отменить интервальный вызов функции, установленный с помощью setInterval(), используют функцию clearInterval().

  
  let timerId = setInterval(() => {
    console.log('Прошло 2 секунды')
  }, 2000)
  
  setTimeout(() => {
    clearInterval(timerId)
    console.log('Сработал clearInterval')
  }, 6000)
  
  console.log(timerId) // 1
  

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

Стоит заметить, что идентификатор, возвращаемый setInterval(), не всегда будет равен 1. Это зависит от того, сколько других таймеров и интервалов было создано до этого.

this и setInterval

Рассмотрим, как контекст this ведет себя при работе с setInterval() в разных ситуациях.

Именованная функция

  
  function message() {
    console.log(this)
  }
  
  setInterval(message, 1000) // Window
  

this в именованной функции, вызываемой в setInterval(), ссылается на глобальный объект window в браузерах и на global в Node.js.

Метод объекта


  const obj = {
    message: 'Прошла секунда',
    printMessage: function message() {
      console.log(`Сообщение: ${this.message}`)
    }
  }

  setInterval(obj.printMessage, 1000) // Сообщение: undefined
  console.log(window.message) // undefined
  

В методе объекта, вызванного через setInterval, this также будет ссылаться на глобальный объект window. Поэтому в нашем случае мы получим undefined, то же самое, что и при window.message.

Стрелочная функция


  const obj = {
    message: 'Прошла секунда',
    printMessage: function message() {
      setInterval(() => {
          console.log(`Сообщение: ${this.message}`)
      }, 1000)
    }
  }

  obj.printMessage() // Сообщение: Прошла секунда
  

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

bind

Можно задать контекст выполнения явно.


  const obj = {
    message: 'Прошла секунда',
    printMessage: function message() {
      console.log(`Сообщение: ${this.message}`)
    }
  }

  setInterval(obj.printMessage.bind(obj), 1000) // Сообщение: Прошла секунда
  

Анонимная функция

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

  
  const obj = {
    message: 'Прошла секунда',
    printMessage: function message() {
      console.log(`Сообщение: ${this.message}`)
    }
  }

  setInterval(function() {
    obj.printMessage()
  }, 1000) // Сообщение: Прошла секунда