The Node Knowledge Challenge — Part 2
This is the second part series of answers to the famous node knowledge challenge taken from book-node-beyond basics.
Please find the first part here
6. What is the difference between setImmediate and process.nextTick ?
NodeJs offers many options to postpone code execution until later. Two of these, setImmediate and process.nextTick, are similar in the way that they make the code run soon.
So, process.nextTick is used when we want to effectively queue the function at the head of the event queue so that it executes immediately after the current function completes i.e. callbacks passed to process.nextTick will usually be called at the end of the current flow of execution, and are thus approximately as fast as calling a function synchronously. Left unchecked, this would starve the event loop, preventing any I/O from occurring whereas setImmediate is used to queue the function behind whatever I/O event callbacks that are already in the event queue so they are queued in the order created, and are popped off the queue once per loop iteration.
So in a case when you are trying to break up a long-running, CPU-bound job using recursion you would want to use `setImmediate` rather than process.nextTick to queue the next iteration as otherwise any I/O event callbacks wouldn’t get the chance to run between iterations.
7. What are the significant differences between spawn, exec, and fork?
spawn, exec, and fork all three are used for creating child processes in NodeJs.The significant difference between spawn and exec is the spawn function does not create a shell to execute the command we pass into it whereas exec does in turn making the latter less efficient as compared to the prior. The exec function has one other major difference. It buffers the command’s generated output and passes the whole output value to a callback function instead of using streams, which is what spawn does.
fork on the other hand as compared to both spawn and exec creates a communication channel with the child process so we can use the send function on the forked process along with the global process object itself to exchange messages between the parent and forked processes.
8. How does the cluster module work? How is it different than using a load balancer?
The cluster module can be used to enable load balancing over an environment’s multiple CPU cores. It’s based on the child process module fork method and it basically allows us to fork the main application process as many times as we have CPU cores. It will then take over and load balance all requests to the main process across all forked processes.
The cluster module is Node’s helper for us to implement the cloning scalability strategy, but only on one machine. The structure of what the cluster module does is simple. We create a master process that forks a number of worker processes and manages them. Each worker process represents an instance of the application that we want to scale. All incoming requests are handled by the master process, which is the one that decides which worker process should handle an incoming request.
The main difference between using a dedicated load balancer as compared to a cluster module will be the capability to redirect requests to multiple machines whereas in the case of a cluster module we can only redirect requests between cores of a single machine. Clearly, being able to redirect requests on the different machine provide us much more options to think about scalability.
9. What will Node do when both the call stack and the event loop queue are empty?
If both the call stack and the event loop are empty and there are no background/asynchronous tasks remaining that are capable of adding to the queue i.e. there are no more event sources, Node will exit.
10. What are V8 object and function templates?
ObjectTemplate gives us JS objects without a dedicated constructor function and prototype. They use Object[.prototype]. Since we can still attach property handlers, they can be useful, whereas FunctionTemplates gives us the added benefit they provide us with a constructor function for use.
11. How can we do one final operation before a Node process exits? Can that operation be done asynchronously?
For doing one final operation before a Node process exists we can register a handler for process.on(‘exit’) or can use SIGINT or SIGTERM
The below gist explains different methods for the same:
// only works when there is no task running// because we have a server always listening port, this handler will NEVER executeprocess.on(“beforeExit”, (code) => {console.log(“Process beforeExit event with code: “, code);});// only works when the process normally exits// on windows, ctrl-c will not trigger this handler (it is unnormal)// unless you listen on ‘SIGINT’process.on(“exit”, (code) => {console.log(“Process exit event with code: “, code);});// just in case some user like using “kill”process.on(“SIGTERM”, (signal) => {console.log(`Process ${process.pid} received a SIGTERM signal`);process.exit(0);});// catch ctrl-c, so that event ‘exit’ always worksprocess.on(“SIGINT”, (signal) => {console.log(`Process ${process.pid} has been interrupted`);process.exit(0);});// what about errors// try remove/comment this handler, ‘exit’ event still worksprocess.on(“uncaughtException”, (err) => {console.log(`Uncaught Exception: ${err.message}`);process.exit(1);});
12. Besides V8 and libuv, what other external dependencies does Node have?
The following are all separate libraries that a Node process can use:
- http-parser
- c-ares
- OpenSSL
- zlib
All of them are external to Node. They have their own source code. They also have their own license. Node just uses them.