1. Single thread feature

  1. A single thread avoids the complex synchronization problems associated with multi-threaded operations.
  2. HTML5 proposes the Web Worker standard, which allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and cannot operate DOM. So, this new standard doesn’t change the single-threaded nature of JavaScript.
  3. It is important to note that triggering and execution are not the same concept. The timer callback must be triggered after the specified delay, but not immediately. It may need to wait. All JavaScript code is executed in a single thread, and events like mouse clicks and timers are executed only when a single JS thread is idle.

2. Task queue

  1. All synchronization tasks are executed on the main thread, forming an execution stack.
  2. In addition to the main thread, there is a “task queue”. 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 to see what events are in it. Those corresponding asynchronous tasks then end the wait state, enter the execution stack, and start executing.
  4. Whenever the main thread is empty, it reads the “task queue”, that’s how JavaScript works.

3. Event Loop

JS creates a loop similar to while (true), and each execution of the body of the loop is called Tick. The Tick process is to check whether there are any pending events, and if there are, the relevant events and the callback function are put into the execution stack and executed by the main thread. Events to be processed are stored in a task queue. That is, each Tick checks whether there are tasks to be executed in the task queue.

The asynchronous operation adds the related callback to the task queue. Different asynchronous operations are added to the task queue at different times, such as onclick, setTimeout, and Ajax processing. These asynchronous operations are performed by webcore in the browser kernel, which contains the three webapis shown in the figure above. These are DOM Binding, Network, and Timer modules.

1. Onclick is handled by the DOM Binding module of the browser kernel. When an event is triggered, the callback function is immediately added to the task queue.

2. SetTimeout will be delayed by the timer module of the browser kernel. When the time is up, the callback function will be added to the task queue.

3. Ajax is handled by the network module in the browser kernel, and the callback is added to the task queue after the network request has completed and returned.

The task queue is above the event loop. After each tick, the event loop checks whether there are any tasks to be executed in the ES6 task queue. That is, the task queue in ES6 has a higher priority than the task (event) queue in the event loop. Promise, for example, uses ES6’s task queue feature.

4. Javascript is single-threaded and browsers are multi-threaded.

The browser kernel is multi-threaded, and they work together under the control of the kernel to keep in sync. A browser implements at least three resident threads: JavaScript engine threads, GUI rendering threads, and browser event-triggering threads.

  1. The JavaScript engine is event-driven, single-threaded execution. The JavaScript engine waits for tasks to arrive in the task queue and then processes them. The browser only has one JavaScript thread running the JavaScript program at any one time.
  2. The GUI rendering thread is responsible for rendering the browser interface, which is executed when the interface needs to be repainted or Reflow due to some action. However, it is important to note that the GUI rendering thread and the JavaScript engine are mutually exclusive. The GUI thread is suspended while the JavaScript engine is executing, and GUI updates are stored in a queue until the JavaScript engine is idle.
  3. The event trigger thread, which, when an event is fired, adds the event to the end of the queue, waiting for the JavaScript engine to process it. These events can come from the block of code currently executing by the JavaScript engine, such as setTimeout, or from other threads in the browser kernel, such as mouse clicks, Ajax asynchronous requests, etc. However, due to the single-threaded nature of JavaScript, all of these events are queued up for the JavaScript engine to handle (asynchronous code is executed only if no synchronous code is executed in the thread).

5. What are the advantages and disadvantages of multithreading?

Advantages: 1. Put time-consuming operations (network request, picture download, audio download, database access, etc.) in the sub-thread to execute, which can prevent the main thread from being blocked; 2, can play the advantages of multi-core processing, improve the UTILIZATION rate of CPU. Disadvantages: 1, each open up a child thread will consume certain resources; 2. It will make the code less readable; 3. If multiple threads access a resource at the same time, resource contention will occur.

6. The browser event loop contains at least two queues, macroTask and MicroTask

  1. Microtasks are tasks that are distributed by the JS engine and are always added to the end of the current task queue. In addition, new microtasks added during microtask processing are added to the end of the queue and executed: Promise, MutaionObserver, process.nexttick (node.js environment)
  2. A macroTask queue is an asynchronous task that is distributed by the host environment. The task queue is a first-in, first-out data structure in which the first event is read first by the main thread: Script, setTimeout, setInterval, I/O, UI interaction events, setImmediate(Node.js environment)
  3. As long as there is a microtask, we must execute the microtask. The currently executed task will be executed. If the event loop still detects the microtask and still performs the microtask after the execution is completed, and if no microtask is detected, we will execute the task in the macro task queue.
  4. Classic interview questions:
async function async1(){
    console.log('async1 start')
    await async2()
    console.log('async1 end')}async function async2(){
    console.log('async2')}console.log('script start')
setTimeout(function(){
    console.log('setTimeout')},0)  
async1();
new Promise(function(resolve){
    console.log('promise1')
    resolve();
}).then(function(){
    console.log('promise2')})console.log('script end')
/* In order of execution, js is always single threaded. The first task must be synchronized, and then according to the order of entering the task queue, first micro, then macro. The micro task is to complete the execution of the existing micro task in the queue at one time, and the macro task is a first-in, first-out. Promise is a constructor that generates a Promise instance when called. The callback function defined in the THEN function is called when the state of the Promise changes. We all know that this callback function is not executed immediately, it is a micro task that is added to the end of the current task queue and executed before the next task starts executing. Async /await comes in pairs, and the async labelled function returns a Promise object, which can be added to the callback using the then method. Statements following await are executed synchronously. But statements under await are added to the end of the current task queue for asynchronous execution as microtasks. * /

/* Answer: Some versions of Node (such as V10.10.0) will exist: Script start -> async1 start -> async2 -> promise1 -> script end -> async1 end -> setTimeout <= node8 version: script start -> async1 start -> async2 -> promise1 -> script end -> async1 end -> promise2 -> setTimeout This is mainly due to the difference between Node.js8 and other versions in that they execute await differently (new Versions of Node (after 11) execute same results as browser, this is the general trend) */
Copy the code