Во многих языках программирования есть функция sleep, которая может задерживать выполнение программы на несколько секунд. Но в JavaScript такая функция отсутствует из-за его асинхронного характера. В этой статье мы рассмотрим как реализовать js sleep самостоятельно.
setTimout и sleep в JavaScript
Для того, чтобы лучше понять проблему, посмотрите следующий код. Он делает запрос к API GitHub для получения пользовательских данных, затем выводит количество публичных репозиториев и, наконец, пошлет в консоль "Привет!"
JS
fetch('https://api.github.com/users/username')
.then(res => res.json())
.then(json => console.log(json.public_repos));
console.log("Привет!");
Но если запустить такой код, то сначала он выведет на экран "Привет!", а уже потом количество публичных репозиториев.
Так происходит, потому что получение данных от API — это асинхронная операция в JavaScript. Интерпритатор JavaScript встретит команду fetch и отправит запрос. Он не будет ждать завершения запроса и выведет "Привет!" в консоль, и потом через пару сотен миллисекунд выдаст количество рекозиториев.
Создаем простую задержку с помощью js setTimeout
Теперь, давайте рассмотрим создание задержки в JavaScript, используя метод setTimeout.
JS
console.log("Привет");
setTimeout(() => { console.log("мир"); }, 3000);
Этот код запишет в консоль "Привет", а затем через 3 секунды "мир" ‐ во многих случаях такой задержки достаточно. Но имейте ввиду, что в js setTimeout ‐ это асинхронный метод. Попробуйте изменить предыдущий код следующим образом:
JS
console.log("Привет");
setTimeout(() => { console.log("мир"); }, 3000);
console.log("Пока");
Этот код выведет: Привет Пока мир.
Вы также можете использовать setTimeout (или его брата setInterval), чтобы заставить JavaScript подождать пока не будет выполнено какое-либо условие. К примеру, вам нужно дождаться появления определенного элемента на странице:
JS
function waitForDOM () {
const container = document.querySelector('container');
if (container.length) {
// Делаем что-то с контейнером
} else {
setTimeout(waitForDOM, 300); // Попробовать снова через 300 миллисекунд
}
}
waitForDOM();
Управление потоком в современном JavaScript
В JavaScript часто бывают ситуации, когда вам нужно подождать, пока то-то произойдет, а затем сделать что-то в ответ. В примере выше мы использовали анонимную callback функцию. Но что если вам нужно подождать несколько событий? В этом случае синтаксис быстро становится довольно грубым.
К счастью, язык значительно изменился за последние несколько лет и теперь у нас есть новые конструкции для этих целей. К примеру, мы может переписать код для получения информации из API GitHub, используя async await.
JS
(async () => {
const res = await fetch(`https://api.github.com/users/username`);
const json = await res.json();
console.log(json.public_repos);
console.log("Привет!");
})();
Теперь код выполняется сверху вниз.
Sleep в JavaScript
Мы уже готовы остановить поток выполнения программы и заставить JavaScript спать. Вот как мы можем это сделать:
JS
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
console.log("Привет");
sleep(2000);
console.log("мир");
В результате сначала в консоли отобразится "Привет", пауза на две секунды, а затем "мир". Функция работает с помощью метода Date.now, получает количество миллисекунд, прошедших с 1 января 1970 года, и присваивает это значение переменной date. Запускает цикл, который будет продолжаться, пока разница между date и currentDate будет меньше нужной задержки.
Улучшаем функцию js sleep
Функция делает то, что нам нужно, но у нее есть недостаток: если вам нужна большая задержка, то она может привести к поломке программы. Объединим методы изученные ранее в статье, чтобы сделать менее навязчивую функцию сна.
JS
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
console.log("Привет");
sleep(2000).then(() => { console.log("мир"); });
Этот код выведет в консоль "Привет", подождет 2 секунды, затем выведет "мир". Внутри мы используем Promise.
Сделаем JavaScript функцию sleep с помощью async ... await:
JS
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function delayedGreeting() {
console.log("Привет");
await sleep(2000);
console.log("мир");
}
delayedGreeting();
console.log("Пока");