Функція сну: Як реалізувати sleep() на JavaScript
Коли потрібна пауза у виконанні коду
JavaScript створив Брендан Айк у 1995 році, його задумано як просту мову для скриптів у браузері. За свою майже тридцятирічну історію він еволюціонував із засобу для додавання інтерактивності на вебсторінках до сильної багатофункціональної платформи. Сьогодні JavaScript використовують не лише в браузерах, а й на серверах (завдяки Node.js), у розробці мобільних застосунків, ігор, IoT-рішень і навіть у машинному навчанні.
Попри свою універсальність, JavaScript має певні обмеження, зумовлені його однопотоковістю й асинхронною природою. Одним із таких обмежень є відсутність вбудованої функції sleep(), яка доступна в інших популярних мовах програмування, як-от Python, Java або C++.
Функція сну дозволяє зробити паузу у виконанні коду на певний проміжок часу. Вона може знадобитися, коли потрібно зімітувати затримку, працювати з таймерами або тестувати асинхронні операції. Відсутність вбудованої функції сну може викликати запитання у початківців: як же створити її аналог? У цьому матеріалі ми розглянемо концепцію функції sleep() у JavaScript та її реалізацію за допомогою setTimeout, промісів (Promise) та синтаксису async/await.
Приклади реалізації функції sleep() на JavaScript
Для початку рекомендуємо звернути увагу на функцію setTimeout. Вона відтерміновує виконання коду на час заданої затримки, але не призупиняє виконання головного потоку коду:
console.log('Привіт'); // Виконається негайно
setTimeout(() => {
console.log('світ!'); // Виконається через 2 секунди
}, 2000);
console.log('JavaScript!'); // Виконається негайно
Результат:
Привіт
JavaScript!
//Через 2 с
світ!
Пояснення:
1.console.log('Привіт') виконується негайно.
2.setTimeout реєструє функцію для виконання через 2 секунди, але головний потік продовжує виконувати наступні інструкції.
3. console.log('JavaScript!') виконується негайно після setTimeout.
4. Через 2 секунди викликається колбек-функція із setTimeout, і тоді друкується «світ!».
В JavaScript програма продовжує виконувати інший код, навіть якщо є асинхронна операція, яка ще не завершена. JavaScript працює в однопотоковому середовищі (single-threaded), яке і називаємо головним потоком. Але асинхронні операції, як-от setTimeout, передаються до позациклових механізмів (наприклад, у браузері або Node.js), і основний потік продовжує виконувати інші завдання.
Це одна з ключових особливостей асинхронної моделі JavaScript, і безпосереднє використання setTimeout для пауз може призвести до неочікуваних результатів. Саме тому розглянемо інший метод застосування setTimeout для реалізації sleep() за допомогою функції та промісу.
Використовуємо проміс, setTimeout і async/await
Створюємо паузу
Щоб реалізувати функцію сну, створімо функцію pause(). Вона повертатиме проміс, виконаний за участю вже раніше розглянутої setTimeout:
function pause(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
Аргументом функції pause() є період часу в мілісекундах, а виконання промісу затримується за допомогою setTimeout. Такий метод дає змогу призупинити виконання програми на вказаний проміжок часу.
Застосовуємо паузу
Щоб задіяти створену раніше функцію pause(), використаємо синтаксис async/await. Він призупиняє асинхронну функцію, коли та натрапляє на інструкцію await, а коли проміс успішно здійснено або він повертає помилку, виконання коду відновлюється.
async function delayedHello() {
console.log('Привіт');
await pause(2000); // Пауза на 2 с
console.log('світ!');
}
Результат виклику функції delayedHello():
Привіт
//Через 2 с
світ!
Пояснення:
1. Команда console.log('Привіт') виконується негайно і виводить текст «Привіт».
2. await pause(2000) викликає функцію pause(2000), яка повертає проміс. Завдяки await виконання коду асинхронної функції delayedHello() призупиняється, поки проміс функції pause() не буде повернено.
3. Після паузи 2 с виконується наступний рядок коду та в консолі зʼявляється «світ!».
Важливо! Ключове слово await використовують тільки в парі з функцією з префіксом async. Застосування await лише призупиняє поточну функцію асинхронізації та не блокує виконання решти скрипту.
Якщо для наведеного прикладу трохи змінити код і застосувати цикл, то можна вивести на консоль цифри від 1 до 5 із затримкою в 1 с:
function pause(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function delayedCount() {
for (let i = 1; i <= 5; i++) {
await pause(1000); // Пауза на 1 с
console.log(i);
}
}
delayedCount();
Результат виклику функції delayedCount():
1
//Через 1 с
2
//Через 1 с
3
//Через 1 с
4
//Через 1 с
5
У циклі for програма викликає функцію сну pause() та виводить в консоль цифри від 1 до 5 з інтервалом в 1 с.
Бонус-метод. Вбудована затримка
Якщо потрібно застосувати паузу лише один раз, не зовсім доцільно створювати окрему функцію сну. Існує швидке рішення довжиною буквально в 1 рядок коду:
await new Promise(resolve => setTimeout(resolve, 1000))
Завдяки цьому коду призупиняється виконання асинхронної функції на 1 с. Він може бути корисним для вбудованих затримок, щоб не створювати й не викликати окремі функції для цього.
Висновок
Розглянутий спосіб створення JavaScript-версії функції sleep() можна вважати зручним інструментом для реалізації затримок у вашому коді. Застосування setTimeout у поєднанні з промісами та async/await враховує асинхронну природу JavaScript та робить ваш код більш читабельним і ефективним.
Використовуючи цей спосіб, ви уникнете блокування JavaScript-коду, зберігаючи неблокувальний характер вебзастосунків. Незалежно від того, для чого вам затримка у виконанні коду, розуміння, як реалізувати її на JavaScript, допоможе покращити власний інструментарій розробника.