This is the 7th day of my participation in the August Text Challenge.More challenges in August

What is a JS thread

To understand what a JS thread is, we should first understand the concept of process and thread.

A browser is an application used to retrieve, display and deliver Web information resources, according to the official browser introduction. In short, a browser is an application. All applications are interpreted and executed on the operating system by the computer’s brain -CPU. In the running process, it exists in the form of processes and threads. An application can have one or more processes, and each program has at least one process.

A process is like a workshop in a factory, and a CPU is like a power supply facility in a factory, except that this facility supplies just enough power to run a workshop. And the thread is the worker in the workshop, each worker is responsible for their own process, together to complete a complex thing.

The difference between a process and a thread has the following characteristics:

  • Process and thread are contained, that is, process contains thread;
  • Processes are more expensive to create than threads;
  • Interprocess communication is slower than interthread communication through IPC.
  • Resources that share memory space between threads, not between processes.

JS threads are the “workers” responsible for processing JavaScript.

How modern browsers work

Currently, there are generally three modes in operating systems:

  • Multi-process mode
  • Multithreaded mode
  • Multi-process + multi-thread mode

One advantage of multi-process mode is that it is more stable than multi-thread mode. In multi-process mode, a single process crash does not affect the running of other processes.

However, in the multi-threaded mode, the crash of any thread will directly lead to the crash of all threads in the whole process. The stability is relatively poor, but communication speed is fast.

Multitasking programs can be implemented by multi-process mode, multi-threading within a single process, or a combination of multi-process and multi-thread mode.

Modern browsers, as we know them, are basically multi-process + multi-threaded applications. Browser multi-process mainly includes Browser process (main Browser process), plug-in process, GPU process, and Browser rendering process.

  • The browser main process is mainly responsible for coordination and control. It controls the user action parts of the application, including the address bar, bookmarks, back and forward buttons, and handles privileges invisible to web browsers, such as Web requests and file access. Responsible for managing individual tabs, creating and destroying other processes, and rendering browser renderers to the user interface.
  • The plugin process is used to control any plug-ins used by the site, such as Flash.
  • The GPU process is used for 3D drawing.
  • Browser rendering process (also known as the browser kernel), by default, we in the new open a browser tabs, will create a rendering process, that is to say each TAB will have a separate rendering process, of course, is not absolute, the browser will sometimes incorporating multiple processes, such as open multiple blank TAB, You will find that multiple blank tabs are merged into a single process. These processes are independent of each other and are mainly responsible for page rendering, script execution and event processing of their respective TAB pages.

Browser multithreading mainly means that the browser rendering process is multithreaded. The rendering process contains:

  • GUI rendering thread: Responsible for rendering the browser interface, parsing HTML, CSS, building DOM trees, layout and drawing, etc.
  • JS engine thread: Also known as THE JS kernel, it is responsible for processing JavaScript scripts (such as the well-known V8 engine), parsing JavaScript scripts, and running the code.
  • Event trigger thread: used to control the event cycle. When the corresponding asynchronous event meets the trigger condition is triggered, the thread will add the event to the end of a task queue to be processed, waiting for the JS engine to be idle.
  • Timer trigger thread: the thread where setInterval and setTimeout reside. The browser timing counter is not counted by the JS engine, but by the timer trigger thread to time and trigger, when the timing is finished, the execution of the event trigger thread, the task added to the task queue, waiting for the JS engine idle execution.
  • Asynchronous HTTP request thread: XHR makes a request through a new thread opened by the browser after the connection. When the callback function is set, the asynchronous thread executes the event to trigger the thread when detecting the state change, and puts the callback into the task queue, waiting for the JS engine to be idle.

Event loop mechanism

Next, we use the above flow chart to analyze, synchronization tasks are completed on the JS engine thread, the current tasks are stored in the execution stack;

When the JS engine thread executes to setTimeout/setInterval, it notifies the timer triggering thread to start timing. After the timing ends, it puts the callback event into the task queue managed by the event triggering thread (the task queue is divided into macro task queue and micro task queue, which we will talk about next).

When the JS engine thread executes to XHR/ FETCH, it notifies the asynchronous HTTP request thread to send a network request. The asynchronous HTTP request thread puts the callback event into the task queue managed by the thread that triggered the event upon successful request.

If there is no task in the execution stack of the JS engine thread, the JS engine thread will ask the event triggering thread whether there is a callback function waiting to be executed in the task queue, if there is, it will be pushed to the execution stack for the JS engine thread to execute; After the JS engine thread is idle, the GUI rendering thread starts working.

Above we have combed through the JS event loop mechanism, next we will understand macro tasks and micro tasks.

console.log('1');

setTimeout(() = > {
  console.log('2');
  new Promise((resolve, reject) = > {resolve()}).then(() = > {
    console.log('3'); })},0);

setTimeout(() = > {console.log('4'); },0);

new Promise((resolve, reject) = > {
  console.log('5'); resolve(); }) .then(() = > {
  console.log('6');
  setTimeout(() = > {console.log('7'); },0);
})

console.log('8');
Copy the code

The first macro task, executes the main thread code, prints 1, 5, 8, when it’s done, starts executing the current micro task queue, prints 6, and there’s an asynchronous task here, and puts it in the task queue. At this point, it means that an event loop has ended, at which point the page UI is normally re-rendered. Then the next macro task is executed, and output 2 indicates that a micro task is detected after the macro task is executed, and output 3 indicates that the next macro task is executed, and output 4 indicates that the next macro task is executed, and output 7 indicates that the next macro task is executed. Therefore, the result is 15862347.

The event loop mechanism maintains an execution stack and task queue, and when code is executed, synchronous tasks are placed in the execution stack in sequence. When the execution stack is idle, asynchronous tasks waiting in the task queue are executed. Tasks are divided into two types: macro tasks and micro tasks. After each macro task is executed, all currently waiting microtasks are executed before the next macro task is executed.