Для начала зададим вопрос: «Что такое Node Js?»

Что ж, большинство людей гуглили это, особенно те, кто относительно плохо знаком с Node JS, и ответ, который мы получаем, в основном такой:

«Node Js - это однопоточная асинхронная неблокирующая модель ввода-вывода, которая выполняет JavaScript на стороне сервера»

По сути, это означает, что код, который мы пишем, выполняется в одном потоке.

Однопоточный режим означает, что у него один стек вызовов, и он может делать только одну вещь за раз. Тогда как NodeJs одновременно выполняет асинхронные неблокирующие операции ввода-вывода?

Node JS построен на движке Chrome V8 JavaScript. Наряду со средой выполнения V8, которая состоит из кучи памяти и стека вызовов, среда NodeJS состоит из очереди обратного вызова,

некоторые другие API и цикл событий. Все это работает вместе для достижения асинхронного неблокирующего характера NodeJS. Мы подробно рассмотрим, запустив фрагменты кода, чтобы увидеть, как среда NodeJS использует все это для достижения асинхронного характера.

Итак, прежде чем мы углубимся, стоит упомянуть одну вещь, что NodeJs не является полностью JavaScript. Он также имеет изрядное количество кода C ++.

Да, вы правильно прочитали. NodeJS содержит код C ++. Как я уже упоминал в предыдущем абзаце, в среде NodeJs есть некоторые другие API, эти API - не что иное, как API C ++.

Вот блок-схема, представляющая архитектуру NodeJS:

Код JavaScript, который мы пишем, JavaScript, который является частью NodeJs, сам V8 и цикл событий, выполняются в одном потоке, основном потоке. Это то, что мы имеем в виду, когда говорим, что NodeJs однопоточный, что все эти вещи выполняются внутри одного потока. Итак, если в нашем коде есть метод JavaScript, который является синхронным и он вызывает некоторый C ++ API, тогда этот код C ++ всегда будет выполняться в основном потоке, тогда как если есть метод JavaScript, который является асинхронным и поддерживается API C ++, тогда иногда он не работает в основном потоке.

Теперь вопрос в том, если он не запускается в основном потоке, то где он запускается? NodeJS однопоточный

Сначала давайте посмотрим, как выполняется следующий фрагмент кода.

Здесь мы будем использовать криптомодуль. Модуль crypto содержит несколько методов, к которым можно получить доступ как синхронно, так и асинхронно.

Это синхронная реализация метода pbkdf2 в криптовалютном модуле. Мы вызываем метод два раза в цикле. Код генерирует вывод следующим образом:

Итак, как мы видим, время выполнения вышеуказанного фрагмента кода составляет почти 319 мс.

Теперь давайте посмотрим еще один фрагмент кода

Здесь у нас есть асинхронная реализация метода pbkdf2. Здесь также мы вызываем метод два раза внутри цикла. Результат для этого:

Выполнение этого кода заняло около 191 мс.

Итак, мы видим, что синхронная реализация выполнялась почти вдвое дольше, чем асинхронная.

Давайте посмотрим на нашу синхронную реализацию. Здесь pbkdf2 вызывается дважды. Теперь, поскольку оба эти вызова являются синхронными, код всегда выполняется в основном потоке. Сначала он попадает внутрь цикла, а затем один раз выполняет crypto.pbkdf2Sync (). Теперь это блокирующий вызов, поэтому выполнение ждет. После завершения этого выполнения во второй раз вызывается crypto.pbkdf2Sync (). Теперь тоже ждет казнь. После завершения второго выполнения метода в конце выполняется строка console.timeEnd ().

Что ж, это было довольно просто. Вся программа выполнялась в одном потоке.

А вот и асинхронная реализация. Каким образом на выполнение требуется меньше времени?

Большинство из нас знает одну вещь: здесь также метод crypto.pbkdf2Sync () был вызван два раза, но они выполнялись параллельно. Ну, NodeJS однопоточный, как же тогда происходит это параллельное выполнение?

Вернемся к диаграмме архитектуры времени выполнения NodeJS. Все упомянутые здесь вещи проявляются в выполнении асинхронной реализации нашего кода. Здесь, когда мы входим в цикл for, он вызывает crypto.pbkdf2 () из основного потока. Как я уже говорил ранее, любой асинхронный метод, поддерживаемый C ++, не будет работать в основном потоке. Этим занимаются API C ++. Теперь API C ++ имеют доступ к потокам и пулам потоков. Поскольку этот crypto.pbkdf2 () поддерживается кодом C ++, C ++ назначает этому методу другой поток, и метод продолжает работать в этом потоке. Теперь главный стек вызовов пуст. Он снова вызывает crypto.pbkdf2 () из основного потока, и происходит то же самое. На этот раз методу также назначается отдельный поток, который выполняется одновременно с первым вызовом.

После завершения выполнения любой из этих функций предоставленный ей обратный вызов помещается в очередь обратного вызова. Здесь, когда оба метода crypto.pbkdf2 () вызывают завершение выполнения, очередь обратного вызова будет иметь два обратных вызова.

После этого появляется цикл событий. Цикл событий в основном действует как диспетчер и отправляет обратные вызовы из очереди обратных вызовов в главный стек вызовов один за другим. Там выполняется то, что находится внутри обратного вызова. Здесь отображается время выполнения.

Таким образом, NodeJS может делать что-то одновременно. Кроме того, некоторые из вас могут подумать, что после этого NodeJS не является таким однопоточным.

Чтобы сказать все правильно, среда выполнения NodeJs является однопоточной, но в фоновом режиме она использует несколько потоков для выполнения асинхронного кода.

Спасибо за терпеливое чтение этой статьи, и я надеюсь, что это помогло вам получить некоторые знания.