Урок 01

Синхронный и асинхронный код

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 делать асинхронные операции.

  1. Call stack — синхронный код
  2. Web APIs — таймеры, сеть, DOM-события (в браузере)
  3. Task queue — очередь готовых callback-ов
  4. 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 управляет очередью задач
  • Синхронный код всегда выполняется раньше асинхронного