Как имитировать методы задержки, сна, паузы и ожидания в JavaScript
Как имитировать методы задержки, сна, паузы и ожидания в JavaScript

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

Как создать функцию сна в JS

У нас также есть простые и понятные решения для тех, кому просто нужно быстрое решение проблемы, не вдаваясь в технические детали. Вот как добавить его в свой набор инструментов JavaScript. sleep Самый прямой способ работы:

Язык кода:javascript
копировать
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

console.log('Hello');
sleep(2000).then(() => { console.log('World!'); });

Запустите этот код, и вы увидите «Hello» в консоли. Затем, через две секунды, появится надпись «World!» v. Это краткий и эффективный способ ввести задержку.

Если вы здесь только ради этого, это здорово! Но если вам интересно «почему» и «как», вам есть чему поучиться. В JavaScript существуют тонкости обработки времени, и, возможно, будет полезно их понять.

Понимание модели выполнения JavaScript

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

Рассмотрим следующий код Ruby:

Язык кода:javascript
копировать
require 'net/http'
require 'json'

url = 'https://api.github.com/users/jameshibbard'
uri = URI(url)
response = JSON.parse(Net::HTTP.get(uri))
puts response['public_repos']
puts 'Hello!'

Как и следовало ожидать, этот код отправляет запрос к API GitHub для получения моих пользовательских данных. Затем он анализирует ответ, выводит количество общедоступных репозиториев, связанных с моей учетной записью GitHub, и, наконец, выводит на экран «Привет!» Исполнение происходит сверху вниз.

Для сравнения, вот версия той же функциональности на JavaScript:

Язык кода:javascript
копировать
fetch('https://api.github.com/users/jameshibbard')
  .then(res => res.json())
  .then(json => console.log(json.public_repos));
console.log('Hello!');

Если вы запустите этот код, он сначала выведет на экран «Привет!», а затем выведет количество общедоступных репозиториев, связанных с моей учетной записью GitHub.

Это связано с тем, что в JavaScript получение данных из API является асинхронной операцией. Интерпретатор JavaScript встречает команду выборки и отправляет запрос. Однако он не ждет завершения запроса. Вместо этого он продолжает выполнение, выводит на консоль «Hello!», а затем, когда запрос возвращается через несколько сотен миллисекунд, выводит количество репозиториев.

Как правильно использовать SetTimeout в JavaScript

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

Стандартный способ создать задержку в JavaScript — использовать его setTimeout метод. Например:

Язык кода:javascript
копировать
console.log('Hello');
setTimeout(() => {  console.log('World!'); }, 2000);

Это выведет на консоль «Hello», а через две секунды — «World!». Во многих случаях этого достаточно: сделать что-то, а затем, после небольшой задержки, сделать что-то еще. Проблема решена!

Но, к сожалению, не всегда все так просто.

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

Например, предположим, что вы запускаете следующий код:

Язык кода:javascript
копировать
console.log('Hello');
setTimeout(() => { console.log('World!'); }, 2000);
console.log('Goodbye!');

Вы увидите следующий результат:

Язык кода:javascript
копировать
Hello
Goodbye!
World!

Обратите внимание, что «До свидания!» предшествует «Мир!»? Это потому, что setTimeout Не блокирует выполнение остального кода.

Это означает, что вы не можете:

Язык кода:javascript
копировать
console.log('Hello');
setTimeout(1000);
console.log('World');

«Привет» и «Мир» сразу же записываются на консоль, без заметной задержки между ними.

Вы также не можете сделать это:

Язык кода:javascript
копировать
for (let i = 0; i < 5; i++) {
  setTimeout(() => { console.log(i); }, i * 1000);
}

Подумайте на секунду, что может произойти с приведенным выше фрагментом кода.

Он не печатает числа с задержкой в ​​одну секунду между каждым числом. 0 приезжать 4. Вместо этого вы фактически получите пять 4. Распечатываются все сразу через четыре секунды. Почему? Потому что цикл не приостанавливает выполнение. оно не будет ждать setTimeout Введите следующую итерацию только после завершения.

Так что же на самом деле делает setTimeout? Теперь давайте посмотрим.

Проверки и лучшие практики для функции setTimeout()

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

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

setTimeout Метод принимает ссылку на функцию в качестве первого параметра.

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

Язык кода:javascript
копировать
function greet(){
  alert('Howdy!');
}
setTimeout(greet, 2000);

Это может быть переменная, указывающая на функцию (функциональное выражение):

Язык кода:javascript
копировать
const greet = function(){
  alert('Howdy!');
};
setTimeout(greet, 2000);

Или это может быть анонимная функция (в данном случае стрелочная функция):

Язык кода:javascript
копировать
setTimeout(() => { alert('Howdy!'); }, 2000);

Вы также можете передать строку кода в setTimeout для его исполнения:

Однако такой подход нежелателен, поскольку:

  1. Его трудно читать (и, следовательно, его сложно поддерживать и/или отлаживать).
  2. Он использует неявное eval,Это потенциальная угроза безопасности
  3. Это медленнее, чем альтернатива, поскольку необходимо вызывать интерпретатор JS.

как упоминалось ранее,setTimeout Отлично подходит для запуска одноразовых действий после задержки, но также может использоваться setTimeout(илиего двоюродный брат setInterval)Приди и уступи дорогуJavaScriptподожди прямоприезжатьудовлетворить условие。Например,Вот как использовать setTimeout Способы ожидания появления элемента на веб-странице:

Язык кода:javascript
копировать
function pollDOM () {
  const el = document.querySelector('my-element');

  if (el.length) {
    // Do something with el
  } else {
    setTimeout(pollDOM, 300); // try again in 300 milliseconds
  }
}

pollDOM();

Это предполагает, что элемент со временем появится. Если вы не уверены, произойдет ли это, вам нужно рассмотреть возможность отмены таймера (используя clearTimeout или clearInterval)。

Использование дополнительных таймаутов в качестве альтернативы функции Sleep в JS.

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

Идея проста: вместо приостановки всего потока выполнения вы используете setTimeout Добавляйте задержку к каждой последующей операции. так,Вы можете создать последовательность отложенных операций,Без блокировки браузера и ущерба для пользовательского опыта.

Вот краткий пример:

Язык кода:javascript
копировать
let delay = 1000; // Старт с задержкой в ​​1 секунду

for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(`Это сообщение ${i + 1}`);
  }, delay);

  delay += 1000; // Задержка каждой итерации увеличивается на 1 секунду.
}

существуют В этом примере,Первое сообщение появится через 1 секунду,Второе сообщение появилось через 2 секунды,и так далее,Пятое сообщение прямого прибытия появилось через 5 секунд.

Преимущества этого подхода в том, что он неблокирует, прост в реализации и не требует знаний promises или async/await。Однако,Он не подходит для сложных асинхронных операций, требующих точного времени и обработки ошибок.

Управление потоком в современном JavaScript

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

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

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

Например, используйте async await,Мы можем переписать исходный API GitHub Код для информации:

Язык кода:javascript
копировать
(async () => {
  const res = await fetch(`https://api.github.com/users/jameshibbard`);
  const json = await res.json();
  console.log(json.public_repos);
  console.log('Hello!');
})();

сейчассуществовать,Код сверхуприезжать Выполнить под。JavaScript Интерпретатор ожидает завершения сетевого запроса, сначала записывая количество общедоступных репозиториев, а затем записывая сообщение «Hello!».

Внедрение функции Sleep в собственный JavaScript

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

Вот как вы можете это сделать:

Язык кода:javascript
копировать
function sleep(milliseconds) {
  const date = Date.now();
  let currentDate = null;
  do {
    currentDate = Date.now();
  } while (currentDate - date < milliseconds);
}

console.log('Hello');
sleep(2000);
console.log('World!');

Как и ожидалось, на консоль выводится «Hello», делается пауза на две секунды, а затем выводится «World!»

Это делается с помощьюDate.nowметод Получено от1970Год1луна1Количество миллисекунд, прошедших со дня,и присвоить это значение date переменная. Затем он создает пустой currentDate переменную, а затем введите do ... while цикл. В цикле он неоднократно получает количество миллисекунд, прошедших с 1 января 1970 года, и присваивает это значение ранее объявленному currentDate переменная. если бы только date и currentDate Если разница меньше требуемого количества миллисекунд задержки, цикл продолжится.

Миссия выполнена, да? Ну, не совсем...

Как написать лучшую функцию Sleep на JavaScript

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

Так что же делать?

Фактически, вы также можете комбинировать методы, изученные ранее в этой статье, чтобы сделать один менее навязчивым. sleep метод:

Язык кода:javascript
копировать
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

console.log('Hello');
sleep(2000).then(() => { console.log('World!'); });

Этот код напечатает «Привет» на консоли.,подожди две секунды,Затем выведите «Мир!» существует нижний слой.,Мы используем setTimeout Метод анализирует promise

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

Это возможно сделать,Но это выглядит не очень хорошо。мы можем использоватьasync ... awaitчтобы украсить его:

Язык кода:javascript
копировать
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedGreeting() {
  console.log('Hello');
  await sleep(2000);
  console.log('World!');
  await sleep(2000);
  console.log('Goodbye!');
}

delayedGreeting();

Это выглядит красивее, но это означает использование sleep Любой код функции должен быть помечен как async

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

Язык кода:javascript
копировать
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedGreeting() {
  console.log('Hello');
  await sleep(2000); // await только приостанавливает текущую асинхронную функцию
  console.log('World!');
}

delayedGreeting();
console.log('Goodbye!');

Приведенный выше код выведет:

Язык кода:javascript
копировать
Hello
Goodbye!
World!

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

Лучшие практики по созданию функций сна JS

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

1. Чистый setTimeout
Язык кода:javascript
копировать
console.log('Hello');
setTimeout(() => { console.log('World!'); }, 2000);

👍 Достоинства: понятный, неблокирующий. 👎 Недостатки: Ограниченный контроль над асинхронными операциями. 📝 Когда использовать: для простых одноразовых задержек.,или Базовый опрос。

2. Инкрементный setTimeout
Язык кода:javascript
копировать
setTimeout(() => { console.log('Hello'); }, 1000);
setTimeout(() => { console.log('World!'); }, 2000);

👍 Преимущества: неблокируется, прост в реализации, не требует знаний. promises или async/await。 👎 Недостатки: Не подходит для сложных асинхронных операций. Обработка ошибок отсутствует. 📝 Когда использовать: для простых последовательностей с временными интервалами.

3. Заблокируйте цикл событий, зациклив его.
Язык кода:javascript
копировать
console.log('Hello');
const date = Date.now();
let currentDate = null;
do {
  currentDate = Date.now();
} while (currentDate - date < 2000);
console.log('World!');

👍 Преимущества: Имитирует традиционное поведение во время сна. 👎 Недостатки: Блокировка всего потока может привести к зависанию пользовательского интерфейса и сбою программы. ⚠️ Настоятельно не рекомендуется: используйте его только в том случае, если вам абсолютно необходимо приостановить выполнение и вы осознаете связанные с этим риски.

4. Используйте Promises и setTimeout
Язык кода:javascript
копировать
const sleep = function(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
console.log('Hello');
sleep(2000).then(() => { console.log('World!'); });

👍 Преимущества: отсутствие блокировки, больший контроль над асинхронными операциями. 👎 Недостатки: Требует понимания обещаний. Более длинные цепочки обещаний могут немного запутать. 📝 когда использовать:Когда вам нужно больше времении Время управления асинхронной работой。

5. Используйте async/await и Promises
Язык кода:javascript
копировать
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedGreeting() {
  console.log('Hello');
  await sleep(2000);
  console.log('World!');
  await sleep(2000);
  console.log('Goodbye!');
}

delayedGreeting();

👍 Достоинства: понятный синтаксис, легко читается, неблокируется. 👎 Недостатки: Необходимость понимать async/awaitиpromises. Требуется наличие внешней функции «обертки». ✅ Настоятельно рекомендуется: это самый современный и чистый метод, особенно когда существует обработка нескольких асинхронных операций.

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

Проблемы синхронизации в JavaScript являются источником головной боли для многих разработчиков, и то, как вы с ними справляетесь, зависит от того, чего вы хотите достичь.

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

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose