Синхронный и асинхронный код
JavaScript однопоточный. В один момент времени выполняется только одна инструкция. Но при этом он умеет делать асинхронные операции: запросы к серверу, таймеры, чтение файлов.
Синхронный код
Выполняется по порядку, каждая строка ждёт предыдущую:
console.log('1');
console.log('2');
console.log('3');
// 1, 2, 3
Если одна операция долгая — всё остальное ждёт:
console.log('начало');
// представим, что это долгий запрос
const data = fetchSync('/api/data'); // блокирует всё
console.log('конец');
Так делать нельзя — браузер зависнет.
Асинхронный код
Долгая операция запускается, но код идёт дальше. Результат приходит, когда готов:
console.log('начало');
setTimeout(() => {
console.log('таймер');
}, 1000);
console.log('конец');
// начало
// конец
// таймер (через секунду)
setTimeout не блокирует. Код идёт дальше, а функция вызовется позже.
Зачем асинхронность
- Отзывчивость UI — интерфейс не зависает во время загрузки данных
- Параллельность — несколько запросов одновременно
- Эффективность — CPU не простаивает в ожидании I/O
Пример: запрос к серверу
Синхронно (не работает в браузере):
const data = fetchSync('/api/users'); // блокирует
console.log(data);
Асинхронно:
fetch('/api/users')
.then((res) => res.json())
.then((data) => console.log(data));
console.log('запрос отправлен');
// запрос отправлен
// [данные придут позже]
Event loop
Механизм, который позволяет однопоточному JavaScript делать асинхронные операции.
- Call stack — синхронный код
- Web APIs — таймеры, сеть, DOM-события (в браузере)
- Task queue — очередь готовых callback-ов
- Event loop — перекладывает задачи из очереди в стек, когда стек пуст
console.log('1');
setTimeout(() => console.log('2'), 0);
console.log('3');
// 1, 3, 2
Даже с 0 миллисекунд setTimeout выполнится после синхронного кода.
Виды асинхронности
- Callback — старая модель, функции обратного вызова
- Promise — современная, цепочки
.then - async/await — синтаксический сахар над промисами
- Event listeners — реакции на события
- Streams — потоковая обработка данных
Итоги
- JavaScript однопоточный, но асинхронный
- Синхронный код блокирует, асинхронный — нет
setTimeout,fetch— примеры асинхронных операций- Event loop управляет очередью задач
- Синхронный код всегда выполняется раньше асинхронного