Ваш код JavaScript всегда выполняется в одном потоке. Это потому, что движок V8 JavaScript не является потокобезопасным.
Однако, как подробности реализации некоторых кодов C ++, могут быть потоки. Например, предположим, что вы пишете некоторый код JavaScript, который подключается к базе данных. Ваш код JavaScript, конечно, будет асинхронным, как любой хороший код Node. Но асинхронное кодирование очень редко встречается в мире C / C ++, поэтому поставщик базы данных, вероятно, не написал асинхронный C / C ++ API.
Поэтому, когда кто-то пишет пакет Node для доступа к базе данных, он должен написать шим, который адаптируется между «блокирующим» поведением C ++ и «неблокирующим, управляемым событиями» поведением Node. Когда вы вызываете, скажем, метод «connect», он переходит к коду C ++, который порождает новый поток, и этот поток выдает (блокирует) вызов «connect» к базе данных, который блокирует поток до тех пор, пока соединение не будет установлено. Затем код C ++ сообщит «соединение установлено» обратно в очередь событий, и в следующий раз, когда основной (JavaScript) поток опрашивает очередь событий, ваш обратный вызов сработает.
Так что да, есть темы, но их использование должно быть полностью прозрачным для вас. Когда вы пишете код Node.js на JavaScript, вам не нужно беспокоиться о потоках - вы просто заботитесь о том, чтобы все произошло, когда они должны. Авторы пакетов могут использовать потоки, но это просто детали реализации, и вам никогда не придется беспокоиться об этом. Ваш код JavaScript никогда явно не использует потоки.