Перейти к содержанию

Как работает Node.js: цикл событий и неблокирующий ввод-вывод

Начало урока

Как работает Node.js: цикл событий и неблокирующий ввод-вывод

Единая модель выполнения, объясняющая, почему асинхронность, таймеры и потоки ведут себя именно так

Главная идея: ваш JavaScript выполняется в одном потоке. Node остаётся быстрым не потому, что запускает ваш код параллельно, а потому, что не даёт этому единственному потоку ждать. Когда работе нужна операционная система (чтение файла, запрос к базе данных, ответ сокету), Node передаёт её наружу, продолжает выполнять другой код и возвращается к вашему коллбэку, когда результат готов. Координатором этого цикла "передал-и-вернулся" является цикл событий.
К концу урока вы сможете:
  • объяснить, что выполняется в единственном главном потоке, а что нет;
  • проследить, как взаимодействуют стек вызовов, цикл событий и его очереди;
  • назвать фазы цикла событий и то, что каждая из них обрабатывает;
  • предсказать порядок setTimeout, setImmediate, Promise и process.nextTick;
  • распознавать блокирующий код и понимать, почему он замораживает весь сервер.

Один поток, один стек вызовов

Node выполняет ваш JavaScript в одном потоке с единственным стеком вызовов. Стек вызовов -- это список функций, которые сейчас выполняются: когда вы вызываете функцию, она кладётся на вершину, а когда она возвращается -- снимается. В каждый момент выполняется только функция на вершине.

Поскольку стек ровно один, две строки вашего JavaScript никогда не выполняются в один и тот же момент. Движок (V8) берёт один кусок работы, выполняет его до конца, затем берёт следующий. Именно поэтому вы никогда не увидите переменную, наполовину изменённую другим потоком: код JavaScript выполняется до завершения. Функцию не прерывает на середине какой-то другой коллбэк; этот другой коллбэк должен ждать, пока стек снова не опустеет.

Эта однопоточная модель -- предпосылка для всего остального в этом уроке. Если запомнить одну фразу, пусть это будет: коллбэк может начаться, только когда стек вызовов пуст. Вся работа цикла событий -- решать, какой коллбэк отправить на этот пустой стек следующим.

Аналогия. Представьте одного повара на кухне (поток). Повар может делать только одно действие за раз. Но умный повар не стоит и не смотрит на духовку, пока печётся торт -- он ставит таймер, начинает нарезать овощи и возвращается к торту, когда таймер прозвенит. Духовка, таймер и курьер -- это помощники вне повара. Цикл событий -- это привычка повара всегда проверять "что для меня сейчас готово?" перед началом следующей задачи.

Продолжите этот урок на YourAIZone

В полном уроке — объяснение целиком, разобранные примеры, частые ошибки, тесты с мгновенной проверкой и ИИ-репетитор. Начните сразу как гость или создайте аккаунт, чтобы сохранять прогресс.

В полном уроке

  • Объяснение целиком
  • Разобранные примеры
  • Частые ошибки и как их избежать
  • Тестовые вопросы: 15
  • ИИ-репетитор, который отвечает на вопросы по теме
  • Отслеживание прогресса для ученика, родителей и учителя