Your understanding of how node works is wrong ... but this is a common misconception because the reality of the situation is actually quite complicated and usually comes down to meaningful little phrases like “node” “inverted”, which simplifies things.
For now, we will ignore explicit multi-processor / multi-threaded processing through cluster and webworker-threads , and just talk about a typical non-thread node.
Node runs in a single event loop. This is single threaded and you only get one thread. All javascript that you write is executed in this loop, and if a lock operation occurs in this loop, then it locks the entire loop and nothing will happen until it completes. This is typically the single-threaded nature of a node that you hear so much about. But this is not the whole picture.
Some functions and modules, usually written in C / C ++, support asynchronous I / O. When you call these functions and methods, they internally control the transfer of the call to the workflow. For example, when you use the fs module to request a file, the fs module passes this call to a worker thread, and this worker waits for a response, which then returns to the event loop that was showing it without it. All this is distracted from you, the node developer, and some of them are distracted from module developers using libuv .
As Denis Dollfus noted in the comments (from this answer to a similar question), the strategy used by libuv to achieve asynchronous I / O is not always a thread pool, especially in the case of the http module, a different strategy is currently used. For our purposes, it is mainly important to note here how the asynchronous context is achieved (using libuv) and that the thread pool supported by libuv is one of several strategies offered by this library to achieve asynchrony.
In the main related touch, there is a much deeper analysis of how node achieves asynchrony, as well as some potential problems associated with this and how to solve them, in this wonderful article . Most of it extends what I wrote above, but additionally points out:
- Any external module that you include in your project that uses its own C ++ and libuv will most likely use a thread pool (I think: access to the database)
- libuv has a default thread pool size of 4 and uses a queue to control access to the thread pool. The result is that if you have 5 lengthy database queries, they all go at the same time, one of them (and any other asynchronous action based on the thread pool) will wait for these queries to complete before they start.
- You can reduce this by increasing the size of the thread pool through the
UV_THREADPOOL_SIZE environment variable while you do this before the thread pool is created and created: process.env.UV_THREADPOOL_SIZE = 10;
If you want traditional multi-processor processing or multi-threading in node, you can get it through the built-in cluster module or other other modules, such as the aforementioned webworker-threads , or you can fake it by doing something to split your work manually using setTimeout or setImmediate or process.nextTick to pause your work and continue in a later cycle so that other processes terminate (but this is not recommended).
Please note: if you write long run / lock code in javascript, you are probably wrong. Other languages will work much more efficiently.