I'm reading a Node.js book to try to get a clear idea of how Node.js handles events, asynchronous functions and their callbacks, non-blocking I/O, etc. Following is a brief synopsis of how I understand the event loop basics, then after that, a few questions I wasn't able to find clear answers to in the book. If anything in my basic understanding is wrong, please correct me. Then the questions follow.
As I understand, Node.js runs all functionality on a single thread. This includes the event loop. In other words, when an event occurs, e.g. an HTTP request, that request goes onto the event queue. The event loop itself pulls one event off the queue at a time and processes it in its entirety. This can mean returning a simple result immediately, or in the case of I/O to a third party (like a database or file system) a non-blocking, asynchronous call is made, with a callback to tell the system what to do when the async function is complete. Meanwhile, all other events in the queue are waiting. In case a developer writes a method that doesn't offload work asynchronously or to workers, the entire server will hang while the task is processed.
If any of that was wrong, please clarify, because it may have a bearing on my understanding of the answer to the following questions, which I hope aren't too stupid.
- File system, database, and other such calls don't block because Node.js offloads them to asynchronous calls, but if Node.js is single threaded, who is listening for new events and managing the event loop? While Node.js is processing some event, who is listening and managing the queuing of new incoming events so they are not lost while Node.js's attention is elsewhere? Do I fundamentally misunderstand how this works? Is there like a daemon running or something, apart from the part of the engine that is running our code, that manages the event queue?
- Similar question for asynchronous functions' callbacks ... who is listening for and managing incoming callbacks while Node.js is already processing some callback or event, so that a callback isn't lost due to its arrival during processing?
- When an async function completes, does the callback interrupt the event loop and take immediate control, or does the return of an async function re-enter the event loop as a new event at the end of the queue and wait its own turn again? In other words, is a callback from an async function treated like any other event, or differently? If it is treated differently, how? Is this a fundamentally stupid question?
- Can a callback be blocking, the same way as a badly written event handlers (e.g. HTTP request handler) can? In other words, can badly written code contained in a callback block the server? (I assume the answer is yes but want to know if I'm right.)
Here is a similar question, with great answers, but a slightly different nuance. This linked question addresses asynchronicity with regard to user code but one of the answers seems to contain an incidental answer to my question. I'm interested in Node's internal workings that the user never interacts with, as well, e.g. who manages new client request insertion into the event queue while Node is blocking, same for callbacks, etc. Is NodeJS really Single-Threaded?