Шпаргалка по setTimeout и setInterval

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

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

Синтаксис и особенности

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

setTimeout(func, delay, …args);
setInterval(func, delay, …args);

Разница между ними в том, что setTimeout задает задержку до единовременного исполнения функции, а setInterval - интервал между многократными вызовами.

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

setTimeout(console.log("Hello!"), 1000);
setTimeout('console.log("Hello!")', 1000);

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

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

const sayHi = () => {
  console.log("Hi!");
};
setTimeout(sayHi, 0);
setTimeout(sayHi, -1000);
setTimeout(sayHi);
// Во всех случаях задержка равно 0

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

const sayHi = () => {
  console.log("Hi!");
};
let delay = 1000;
setTimeout(sayHi, delay);
delay = 2000;
// Таймер отработает чере 1 секунду

Как Вы уже могли заметить, отложенная функция не вызывается внутри setInterval и setTimeout, а только передается в них. Аргументы отложенной функции передаются как параметры самого таймера:

const greating = (name) => {console.log(`Hi, ${name}!`)};
setTimeout(greating, 1000, "John");

Отмена таймеров

Вызов setTimeout или setInterval возвращает id таймера. Передав этот идентификатор в функцию clearTimeout или clearInterval мы отменим срабатывание таймера. Id всех рассматриваемых таймеров хранятся в одном месте и обе функции отмены делают идентичную работу просто удаляя из общего хранилища таймер по идентификатору. Несмотря на это, желательно использовать для отмены setTimeout именно clearTimeout и clearInterval для setInterval, что бы повысить читаемость кода.

const sayHi = () => {console.log("Hi!");};
const id = setTimeout(sayHi, 2000);
clearInterval(id);
//таймер отменен, но при чтении не понятно что за интервал
clearTimeout(id);
//делает то же самое, но читается намного понятнее

Реальная длительность задержек

Передавая в setTimeout и setInterval нужное время задержки вызова функции, мы ожидаем что именно через такое количество миллисекунд вызов и произойдет, но на практике время задержки может отличаться, при чем довольно сильно. Вызвано такое поведение особенностями работы Цикла Событий (Event Loop) в браузерах и Node JS. Не будем вдаваться в подробности т.к. это тема для отдельной статьи. Для понимания причин отличия переданного значения задержки от реальных результатов работы кода нам достаточно знать, что вызов функции из таймера происходит только после завершения некоторых других операций, таких, как, например синхронные операции, события WebApi, Promise и т.п. Даже если задана задержка в 0 миллисекунд.

setTimeout(() => {
  console.log("Таймаут");
}, 0);
let myPromise = new Promise((resolve, reject) => {
  console.log("Создание промиса");
  resolve();
});
myPromise.then(() => {
  console.log("Обработка промиса");
});
console.log("Синхронный код");
//Порядок вывода в консоль будет таким:
//1: Создание промиса
//2: Синхронный код
//3: Обработка промиса
//4: Таймаут

При этом длительные операции могут сильно отсрочить срабатывание таймера, например, если это сложный расчет, сильно нагружающий процессор.

setTimeout(() => console.log('Таймер на 0.1с'), 100);
let i = 0;
for(let j = 0; j < 100000000; j++) {
  // сложная операция, занимающая больше 100 мс
  i++;
}
//В консоли наш текст появится спустя более чем 100мс

Источник: https://habr.com/ru/articles/752592/


Интересные статьи

Интересные статьи

Идея этого поста - шпаргалка на будущее, но я буду рад, если кому-то пригодится приведенная информация.Если Вы читаете это, значит примерно представляете, что такое Ring. В этом посте речь только об а...
Доброго времени суток, друзья! Изучение настоящей шпаргалки не сделает вас мастером SQL, но позволит получить общее представление об этом языке программирования и возможностях, которые...
Привет, меня зовут Григорий Бизюкин, я преподаватель Школы разработки интерфейсов и фронтенд-разработчик в Яндексе. Давайте поговорим о функциональном программировании в мире JavaScript. ...
Ни для кого не секрет, что в дотнет завезли интринсики. Я писал об этом и до того, как они появились и после. Плюс ещё посты на Хабре, например этот. И всё, казалось бы, замечательно,...
Когда-то я собеседовался на должность C++ разработчика в одну приличную и даже известную контору. Опыт у меня тогда уже кое-какой был, я даже назывался ведущим разработчиком у тогдашнего своего р...