Синхронний і асинхронний код
Синхронний код виконується строго по порядку: наступна операція не почнеться, доки не завершиться попередня. Асинхронний код дозволяє програмі працювати далі, не чекаючи на завершення довгих операцій, як-от мережеві запити чи таймери.
Теорія
TL;DR
- Синхронно означає «по порядку і блокуюче»: кожен рядок чекає на попередній.
- Асинхронно означає «неблокуюче»: довга операція передається зовнішньому API, а код іде далі.
- JavaScript має один потік (single thread), але завдяки event loop працює асинхронно.
- Готовий результат потрапляє в чергу завдань і виконується, коли звільниться стек викликів (call stack).
- Асинхронність реалізують callbacks, Promises, async/await та обробники подій.
Швидкий приклад
console.log('1');
setTimeout(() => {
console.log('2'); // runs later
}, 1000);
console.log('3');Вивід:
1
3
2Чому так:
setTimeout- асинхронна операція, вона планується на майбутнє.- JavaScript не чекає на її завершення, а йде далі.
- Коли таймер спрацює, функція потрапить у чергу подій (event queue) і виконається пізніше, щойно звільниться стек викликів.
Синхронне виконання
console.log('1');
console.log('2');
console.log('3');Вивід:
1
2
3Усе виконується построково: наступна команда не почнеться, доки не завершиться попередня. Це і є синхронне виконання. Схематично:
[ Завдання 1 ] -> [ Завдання 2 ] -> [ Завдання 3 ]Поки одна операція виконується, інші чекають.
Як це працює під капотом
JavaScript має один потік виконання, але завдяки event loop (циклу подій) може працювати асинхронно та неблокуюче.
- Довгі операції (наприклад,
fetch,setTimeout, I/O) передаються у зовнішні API середовища (браузера або Node.js). - JavaScript продовжує виконувати решту коду.
- Коли операцію завершено, результат повертається у чергу колбеків і виконується пізніше.
Схематично:
[ Завдання 1 (асинхронне) ] -> [ Завдання 2 ]
|
(результат повернеться пізніше)Реальні приклади
| Ситуація | Синхронний код | Асинхронний код |
|---|---|---|
| Читання файлу | JavaScript чекає, доки файл повністю прочитається | JavaScript віддає задачу API і працює далі |
| Запит на сервер | Код «заморожується» до відповіді | Код іде далі, відповідь обробляється пізніше |
| Цикл на мільйон ітерацій | «Підвішує» інтерфейс | Виконується у фоні (через Web Worker або асинхронно) |
Чим реалізується асинхронність
| Механізм | Приклад |
|---|---|
| Callbacks (колбеки) | setTimeout(() => {...}, 1000) |
| Promises | fetch('/data').then(...) |
| async / await | const data = await fetch('/data') |
| Обробники подій | button.addEventListener('click', ...) |
Приклад справжньої асинхронності з fetch:
console.log('Start');
fetch('https://api.example.com/user')
.then(res => res.json())
.then(data => console.log('Response received:', data));
console.log('End');Вивід:
Start
End
Response received: {...}Поки сервер відповідає, JavaScript не чекає, а йде далі і повертається до колбека тоді, коли дані готові.
Підсумок
| Відмінність | Синхронний код | Асинхронний код |
|---|---|---|
| Виконання | Послідовно, блокуюче | Через події, неблокуюче |
| Затримки | Блокують програму | Не заважають виконанню |
| Використовується для | Простих і коротких операцій | Запитів, таймерів, файлів, API |
| Приклад | console.log() | setTimeout(), fetch() |
| Механізм | Стек викликів | Event loop і черги завдань |
Типові помилки
- Вважати, що асинхронний код виконується «паралельно» в окремому потоці. У JavaScript потік один, паралелізм дає середовище, а не сам рушій.
- Очікувати, що
setTimeout(fn, 0)виконаєfnнегайно: колбек усе одно чекає, доки звільниться стек викликів. - Записувати результат
.then()у зовнішню змінну і читати її наступним рядком: там ще будеundefined. - Ставити важкий синхронний цикл поруч з асинхронним кодом: він блокує event loop, тому таймери та відповіді мережі «зависають».
- Плутати
awaitіз блокуванням усієї програми:awaitпризупиняє лише поточну async-функцію, а не весь потік.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.