Async identifier is not enough to create non-blocking method in Node Js
Before trying Node JS, there is a significant concept about how this single-threaded programming language deal with the blocking operation.
In Node.js official site:
What is the Event Loop?
The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible.
Since most modern kernels are multi-threaded, they can handle multiple operations executing in the background. When one of these operations completes, the kernel tells Node.js …
What operation can be offloaded to kernels?
When reading a file, making a RESTful api request or retrieving date from database, the module always provide a callback, so the main thread of JavaScript code can be notified and handle the response. Those operation actually are non-JavaScript process.
- File System: e.g. fs module
- HTTP: e.g. http module
- Database communication: e.g. pg module
- and more …
Why Async method still block other methods?
The reason is only non-JavaScript process can be offloaded to kernels, if there is a CPU intensive logic in the async
method, it still consumes the only one main thread, below code snippet can tell:
There are three async methods, the first one (1) is a JavaScript operation which iterate 99 times, the second (2) method is a I/O operation which reads a external file, the last one (3) is a small JavaScript method.
When executing the above logic node ./async_await_example.js
, start()
will be triggered, and the Promise.all
would await those three async methods (1), (2) and (3). And we got the below result.
> node ./async_await_example.jslongRunJsFunction finished
quickRunJsFunction finished
IONonJsFunction finished
all async methods finished
The result showed that the first long running JavaScript method longRunJsFunction
blocked the other two async methods, however the second I/O method IONonJsFunction
didn’t block as it returned in the end
To avoid writing blocking JavaScript logic
- Pass the high CPU usage operation to other service, and retrieve via HTTP call
- Split the big chunk of code into pieces, so that other method can wait shorter to execute
- To handle response from database call, try to manipulate the data structure in SQL query instead of iterate each row in Node JS