← Назад к вопросам

Как написать Wait без использования Promise?

2.0 Middle🔥 231 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как написать Wait (задержку) без использования Promise

В JavaScript есть несколько способов добавить задержку без использования Promise. Рассмотрим основные подходы.

1. setTimeout с callback функцией

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

// Простая задержка
setTimeout(() => {
  console.log('Выполнилось через 2 секунды');
}, 2000);

// С параметрами
setTimeout((name) => {
  console.log(`Привет, ${name}!`);
}, 1000, 'Иван');

// С переменной
const delay = 3000;
setTimeout(() => {
  console.log('Задержка в 3 секунды');
}, delay);

2. setInterval для повторяющейся задержки

setInterval — выполняет функцию многократно через равные промежутки времени.

let counter = 0;

const intervalId = setInterval(() => {
  counter++;
  console.log(`Счётчик: ${counter}`);
  
  // Остановить интервал при достижении 5
  if (counter === 5) {
    clearInterval(intervalId);
    console.log('Интервал остановлен');
  }
}, 1000);

3. setTimeout с рекурсией

Можно создать функцию, которая повторяет действие через задержку:

function repeatWithDelay(callback, delay, times) {
  let count = 0;
  
  function execute() {
    callback(count);
    count++;
    
    if (count < times) {
      setTimeout(execute, delay);
    }
  }
  
  execute();
}

// Использование
repeatWithDelay((i) => {
  console.log(`Итерация ${i + 1}`);
}, 1000, 5);

// Выведет:
// Итерация 1
// Итерация 2
// Итерация 3
// Итерация 4
// Итерация 5

4. requestAnimationFrame для плавной анимации

requestAnimationFrame — синхронизируется с частотой обновления браузера (обычно 60 FPS). Используется для анимаций.

let startTime = null;
const duration = 2000; // 2 секунды

function animate(currentTime) {
  if (startTime === null) {
    startTime = currentTime;
  }
  
  const elapsed = currentTime - startTime;
  const progress = elapsed / duration; // 0 до 1
  
  console.log(`Прогресс: ${(progress * 100).toFixed(1)}%`);
  
  if (progress < 1) {
    requestAnimationFrame(animate);
  } else {
    console.log('Анимация завершена');
  }
}

requestAnimationFrame(animate);

5. Event Listeners с таймерами

Можно использовать события для триггера функций:

const button = document.querySelector('button');
let isWaiting = false;

button.addEventListener('click', () => {
  if (isWaiting) {
    console.log('Пожалуйста, подождите...');
    return;
  }
  
  isWaiting = true;
  console.log('Обработка запроса...');
  
  setTimeout(() => {
    isWaiting = false;
    console.log('Запрос завершен!');
  }, 3000);
});

6. Debounce функция (задержка выполнения)

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

function debounce(callback, delay) {
  let timeoutId = null;
  
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      callback.apply(this, args);
    }, delay);
  };
}

// Использование
const input = document.querySelector('input');

const handleSearch = debounce((value) => {
  console.log(`Поиск по: ${value}`);
  // API запрос
}, 500);

input.addEventListener('input', (e) => {
  handleSearch(e.target.value);
});

7. Throttle функция (ограничение частоты)

Throttle — выполняет функцию максимум один раз за указанный период.

function throttle(callback, limit) {
  let inThrottle = false;
  
  return function(...args) {
    if (!inThrottle) {
      callback.apply(this, args);
      inThrottle = true;
      
      setTimeout(() => {
        inThrottle = false;
      }, limit);
    }
  };
}

// Использование
const handleScroll = throttle(() => {
  console.log('Скролл срабатывает максимум раз в 1 секунду');
}, 1000);

window.addEventListener('scroll', handleScroll);

8. Callback при загрузке ресурса

const img = new Image();

img.onload = () => {
  console.log('Изображение загружено');
};

img.src = 'path/to/image.jpg';

// С задержкой
setTimeout(() => {
  console.log('Проверка после загрузки');
}, 2000);

Сравнительная таблица

МетодИспользованиеОсобенности
setTimeoutОдноразовая задержкаПростой и распространённый
setIntervalПовторяющаяся задержкаНужно вручную остановить
requestAnimationFrameАнимацииСинхронизирован с браузером
debounceОтложенное выполнениеСбрасывается при повторном вызове
throttleОграничение частотыВыполняется максимум один раз за период

Практический пример: Простая анимация загрузки

function showLoadingAnimation() {
  const loader = document.querySelector('.loader');
  let dots = 0;
  
  const intervalId = setInterval(() => {
    dots = (dots + 1) % 4;
    loader.textContent = 'Загружаем' + '.'.repeat(dots);
  }, 500);
  
  // Остановить через 5 секунд
  setTimeout(() => {
    clearInterval(intervalId);
    loader.textContent = 'Готово!';
  }, 5000);
}

showLoadingAnimation();

Отмена задержки

Все таймеры можно отменить:

// Отменить setTimeout
const timeoutId = setTimeout(() => {
  console.log('Это не выведется');
}, 5000);

clearTimeout(timeoutId);

// Отменить setInterval
const intervalId = setInterval(() => {
  console.log('Интервал');
}, 1000);

clearInterval(intervalId);

Главное отличие от Promise

setTimeout/setInterval — это callback-based подход (старый стиль):

setTimeout(() => {
  console.log('Готово');
}, 1000);

Promise — это более современный подход с лучшей обработкой ошибок и цепочкой операций:

new Promise(resolve => {
  setTimeout(resolve, 1000);
}).then(() => {
  console.log('Готово');
});

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

Как написать Wait без использования Promise? | PrepBro