As we learn about Node, we need to understand some basic concepts. What is Node, what problems it solves, and the features of Node. These include confusing processes and threads, synchronous and asynchronous, blocking and non-blocking, and the core concept of Event loops in Node.

1. What is Node?

Node.js is based on Chrome V8 Node is not a language that allows JavaScript to run at the back end of the runtime, and does not include the full set of JavaScript because it does not include DOM and BOM in the server. Node also provides some new modules such as HTTP and FS modules. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, and Node.js’s package manager, NPM, is the largest open source library ecosystem in the world. Event-driven and non-blocking IO will be covered later. At this point we have a simple idea of Node.

2. What problems does Node solve?

Node has significant performance advantages in high concurrency,I/O intensive scenarios

  • High concurrency refers to concurrent access to the server at the same time
  • I/O intensive refers to the file operation, network operation, database, the relative CPU intensive,CPU intensive refers to the logical processing operation, compression, decompression, encryption, decryption

The main scene of Web is to receive requests from clients to read static resources and render interfaces, so Node is very suitable for Web application development.

3. Processes and threads

Process is the basic unit of the operating system to allocate resources and schedule tasks. Thread is a program running unit built on the process. There can be multiple threads on a process.

3.1 Talk about browsers

  • User interface – includes address bar, forward/back buttons, bookmark menu, etc
  • Browser engine – passes instructions between the user interface and the rendering engine (the main process of the browser)
  • Rendering engine, also known as browser kernel (browser rendering process)
  • One plug-in for one process (third-party plug-in process)
  • GPU Improves web browsing experience (GPU process)

So the browser is multi-process, and from our point of view we care more about the browser rendering engine

3.2 Rendering Engine

The rendering engine is multi-threaded internally, containing the two most important threads, the UI thread and the JS thread. It is important to note that the UI thread and the JS thread are mutually exclusive, because the results of the JS run affect the results of the UI thread. UI updates are stored in the queue and executed as soon as the JS thread is idle.

3.3 Other Threads

  • The browser event trigger thread (used to control the event loop and hold setTimeout, browser events, ajax callback functions)
  • Timer trigger thread (setTimeout timer thread)
  • Asynchronous HTTP request thread (Ajax request thread)

3.4 JS single thread

Javascript was originally designed to be single-threaded, so why not multi-threaded? Wouldn’t it be confusing if multiple threads were manipulating the DOM at the same time? By single-threaded I mean that the main thread is single-threaded, so in Node the main thread is still single-threaded. Let’s draw a picture of single-threaded versus multi-threaded

  • Tomcat, iis service
  • The node service

Single-threaded features save memory and do not need to switch execution contexts. And the single thread does not need to deal with the problem of locking, here is a brief description of the concept of locking. For example, after class, everyone has to go to the toilet. There is only one toilet, which means that everyone has to access the same resource. Then whoever comes in first must lock up. For Node. Class is over a person to go to the toilet, so avoid the lock problem!

4. Queues and stacks

  • The queue
setTimeout(function(){
    console.log(1)
})
setTimeout(function(){
    console.log(2)
})
setTimeout(function(){
    console.log(3)
})
Copy the code

When a timer is set, the callback functions corresponding to the timer are placed in a queue in sequence.

  • The stack
function stack(){
    console.log(1);
    fn1();
    function fn1(){
        console.log(2);
        fn2();
        function fn2(){
            console.log(3)
        }
    }
}
stack();
Copy the code

We can see that js is executed in the global context, the call is stacked in the order of stack->fn1->fn2, when the scope is destroyed first need to destroy fn2->fn1->stack

5. Event Loop in the browser

  • 1. All synchronization tasks are executed on the main thread, forming an execution stack
  • 2. In addition to the main thread, a task queue exists. Whenever an asynchronous task has a result, an event is placed in the task queue.
  • 3. Once all synchronization tasks in the execution stack are completed, the system reads the task queue and puts the events in the queue into the execution stack for execution
  • 4. The main thread reads events from the task queue in a continuous loop

This whole mechanism is called an Event Loop

6. Event Loop in Node

Let’s start with a picture of how Node works

  • 1. The JS code we write will be handed over to the V8 engine for processing
  • 2. NodeApi may be called in the code, and Node is handed over to the Libuv library
  • 3. Libuv implements asynchronous I/O through blocking I/O and multithreading
  • 4. In an event-driven way, put the result into the event queue and finally deliver it to our application.

There is such an event loop mechanism inside Libuv. The event loop is initialized when node starts

┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ┌ ─ > │ timers (timer) │ | | execution setTimeout and | | | setInterval callback. | │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ I/O callbacks | │ | processing network, flow, TCP error | | | callback | │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ idle, Prepare │ | | | use within the node │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ poll (polling) │ │ incoming: │ | | execution poll in the I/o queue | < ─ ─ ─ ─ ─ ┤ connections, │ | | check whether the timer is then | │ data, Etc. | │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ check (check) │ | | deposit setImmediate callback | │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ └ ─ ─ ┤ close callbacks | │ closed callbacks such as | | sockect) on (' close ') | └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘Copy the code

Here, each stage corresponds to an event queue. When the Event loop is executed to a certain stage, the queues corresponding to the current stage will be executed successively. When the queue completes or the number of executions exceeds the upper limit, it moves to the next phase. Here we focus on the poll phase

6.1 poll phase

6.2 setTimeout and setImmediate

The two are very similar, but the difference depends on when they are called.

  • SetImmediate setImmediate is designed to perform when the poll phase is complete, the Check phase;
  • SetTimeout design is executed when the poll stage is idle and the set time reaches. However, the call order of the two in the timer phase depends on the context of the current Event loop. If they are called outside the asynchronous I/O callback (called inside THE I/O because the next phase is the check phase), the order of execution is uncertain, and the time before the loop is executed needs to be determined.
setTimeout(function timeout () {
  console.log('timeout'); }, 0);setImmediate(function immediate () {
  console.log('immediate');
});
Copy the code

6.3 process. NextTick

NextTick does not belong to a phase of the event cycle; it is executed in the middle of a phase switch, creating a nasty piece of code

setImmediate(function(){
    console.log(1);
    process.nextTick(function(){
        console.log(2);
    });
});
process.nextTick(function(){
    console.log(3);
    setImmediate(function(){ console.log(4); })}); // 3, 1, 4, 2Copy the code

NextTick: nextTick: nextTick: nextTick: nextTick: nextTick: nextTick: nextTick (Do not call nextTick recursively, or callback in later stages will not execute)

7. Macro and micro tasks

Tasks can be divided into macro tasks and micro tasks

  • Macro-task: setTimeout, setInterval, setImmediate, I/O
  • Micro-task: Process. nextTick, native Promise(some implemented promises put then methods in macro tasks),Object.observe, MutationObserver
process.nextTick > promise.then > setTimeout > setImmediate
Copy the code

From the above we know the order of execution of tasks. Note that the promise. then method is defined to execute after nextTick

8 Synchronous asynchronous and blocking non-blocking

Synchronous asynchrony depends on the caller, blocking non-blocking depends on the caller

  • A blocking call means that the current thread is suspended until the result of the call is returned. The calling thread does not return until it gets the result.
  • A non-blocking call does not block the current thread until the result is not immediately available.

Here we explain the concept of Node in detail, like to click on it! You can give me a tip if you support me