How does Node.js work asynchronously without multithreading?
It’s all a hoax. Node is multithreaded.
The main event loop is single-threaded by nature. But most of the i/o (network, disk, etc) is run on separate threads, because the i/o APIs in Node.js are asynchronous/non-blocking by design, in order to accommodate the event loop.
However, in some ways, calling Node asynchronous is a misnomer IMO, because almost all the code that the developer sees is in fact synchronous, not asynchronous. In other words, for the average program a Node.js developer writes, all the asynchrony is abstracted away inside the i/o related APIs.
Just because you don’t see it, doesn’t mean it’s not there or that it’s not important.
One of the biggest pluses about Node is the very fact that more often than not all the code the developer writes is running on one thread in an event loop – that’s the rub – you don’t have to deal with a multi-threaded environment because it’s abstracted away.
So yes, you can’t get away from multithreading, even in Node.js. However, with the Node.js event loop, you can truly avoid many of the pitfalls of more traditional multithreaded servers and programs.
Of course, on the backend, there are. However, these are not explicitly exposed to your code, so you can’t worry about them other than by knowing that I/O interactions e.g. with the database, or with other processes will be asynchronous from the perspective of each request since the results from those threads are returned via the event loop to your code. Compared to the Apache model, there are a lot less threads and thread overhead, since threads aren’t needed for each connection; just when you absolutely positively must have something else running in parallel and even then the management is handled by Node.js.