• pre-notify
  • The term
  • Why is JS designed to be single threaded?
  • JS does not have only one thread, but the main thread is single threaded
  • Asynchronous tasks and event loops
    • In the Node. Js の EventLoop
    • Microtasks and macro tasks
      • Other microtasks
  • Q
      1. SetTimeout, setImmediate?
      1. NextTick and Promise. Then who is faster?
      1. NextTick is nested with other timers
      1. Is the timer callback always executed at the specified time?
  • About the Browser model

pre-notify

This article is mainly based on the summary of online resources, if there is any wrong, please correct.

reference

  • Node timer description
  • A simple explanation of processes and threads
  • setImmediate() vs nextTick() vs setTimeout(fn,0) – in depth explanation
  • The Node.js Event Loop, Timers, and process.nextTick()
  • Don’t confuse NodeJS with event loops in browsers

The term

Synchronous: Synchronous task

Asynchronous: asynchronous task

Task Queue /callback Queue: indicates a task queue

Execution context stack: The execution context stack

Heap heap:

Stack stack:

Macro-task: indicates a macro task

Micro-task: indicates a micro-task

Why is JS designed to be single threaded?

Well, it’s worth exploring this historical issue before we dive into the subject, because if JS weren’t single-threaded it wouldn’t have spawned asynchronous tasks and event loops.


Js originally ran on the browser side, and its main function was to interact with the user (receiving user input and giving customized responses) and manipulate the DOM (various effects, controlling input and output).

So there is a saying on the web, for example, that two threads, one adding a DOM element a and the other removing a DOM element A, then the browser has to decide which one to listen to, which adds complexity to the language design.

B: well… If that’s not enough to convince you, I think you should think back to when javascript was being developed

In fact, I think that’s one of the reasons why it’s important, well, that’s something I can relate to, and that’s

My javascript was created in 10 days… So, what else do you want?

JS does not have only one thread, but the main thread is single threaded

H5 has a new API called WebWorker that allows you to create child threads.

//index.html
let worker = new Worker('./worker.js'); // Send the content to the worker thread, which can throw the result back to worker.postmessage ('Send instructions to the workers you hire.');

worker.onmessage = function(e){ console.log(e.data); } //worker.js window.onmessage =function(e){
	console.log(e);
  this.postMessage('Your worker tells you he's been ordered to start! ');
};
Copy the code


Note: it is not parallel to the main js thread. The main thread controls the Webworker, but the webworker cannot manipulate the DOM or get documents or Windows.

Asynchronous tasks and event loops

Single thread while simple, is not easy to get wrong, but there is a problem, this goods has always been a person at work, if involves reading writing this I/O behavior, then CPU resources not only is no problem of waste (webworker part actually possibly to try to solve this problem), we still waiting for it to read and write at the back of the code is to perform, This is what is called standing nabra na-sa -!

So, in order to solve this problem, Javascript divides the execution of tasks into two ways: Synchronous /synchronous and asynchronous /asynchronous, in the case of an I/O operation that requires a long wait like the one above, we dispatch it as an asynchronous task and notify us when it completes.

We say that we distribute to asynchronous tasks, so who does the distribution distribute to?

In the browser kernel, in addition to JS threads and user interface Backend /UI Backend threads, there are other threads, such as browser event trigger threads, timer trigger threads, and asynchronous HTTP request threads, to which asynchronous tasks are assigned. (Check out the last part of this article if you don’t know much about it.)

When these asynchronous tasks are processed in the corresponding thread, their callbacks are added to the callback Queue. On the other hand, the execution stack of the JS main thread will continuously detect the callback queue once all synchronous codes are executed. As long as there are tasks in the queue, they will be extracted and executed in the execution stack.

The following is a diagram that has been widely circulated on the Internet

The JS main thread reads events from the callback queue to the execution stack, which is also called EventLoop.

In the Node. Js の EventLoop

The event loop in node is different from the event loop in the browser. The event loop in Node is divided into six phases. Each phase has a CallBcak queue.

  • Timer, perform setTimeout and setInterval callbacks
  • I/O Callbcacks, handling network, stream, TCP callBCAK, and errors
  • Idle. The prepare node is used internally
  • Poll, which waits for I/O execution until cb is obtained
  • Check, which handles setImmediate callbacks
  • Close Callbcaks, which handles closed callbacks such as socke.on(‘close’)

Microtasks and macro tasks

There are two main types of asynchronous tasks,

One is called macro task, which takes a long time, such as setTimeout, I/O reading and writing, and AJAX.

The other are micro tasks, such as nextTick and Promise. (Even if the timer’s delayt time is set to 0, it is still a macro task and will be executed after the execution of the micro-task in this round.)

The difference between macro tasks and micro tasks is that micro tasks are added to the cycle, while macro tasks are executed in the second cycle.

What is this cycle? The JS main thread will extract the task from the task queue to execute in the execution stack, and each execution may generate a new task. For these tasks, this execution is the round of these new tasks before extracting the new task from the task queue to execute the stack.

(danger) note: In Node, microtasks are triggered before entering the event loop and during state transitions. This means that if the CallBCAk queue in a state has not been cleared of Cb’s, microtasks will not be executed immediately after a callback is completed, as in the browser. Instead, it waits for the queue to clear.

Other microtasks

  • MutationObserve(incompatible),
  • MessageChannel

Q

1. SetTimeout, setImmediate

setTimeout(function(){
console.log('Timeout');
})
setImmediate(function(){
console.log('Immediate');
})
Copy the code

SetTimeout is the first phase of the Node event loop, but setTimeout will be 1ms+ even if delay is set to 0 (Node is not that precise), so setTimeout may not be ready for the first event loop. I’m going to let setImmediate do it first.

But is that really going to happen?

B: well… I clicked dozens of times, all setTimeout.

Here’s another scenario where setImmediate must go first

fs.readFile('./1.txt'.function(){
    console.log('fs');
    setTimeout(function(){
    	console.log('timeout');
    });
    setImmediate(function(){
    	console.log('setImmediate');
    });
})
Copy the code

This is because the POLL phase of the event loop is where THE FS I/O callback is executed, and the next phase, called Check, is where setImmediate is stored.

2. NextTick and Promise. Then who is faster?

NextTick fast. That’s how it’s designed

3. The nextTick timer is nested with other timers

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

The reason is that the nextTick execution in Node is not exactly the same as it is in the browser. Although they are executed the first time the event loop is entered, if nextTick is added later, node will execute it only during a phase transition, whereas the browser will execute it as soon as nextTick is added.

The reason for this difference is that the node event loop has six states, each of which is a CallBCak queue. NextTick is executed only when the callback queue of a state is empty.

4. Is the callback function specified by the timer executed within the specified time?

Not necessarily. Regardless of the transition between states in node event loop 6, the event loop in the browser can also take longer than the timer specified event and cause the timer callback to be delayed.

About the Browser model

Well, the picture above. It’s also a very popular one

Browsers are multi-process, and each process manages a different part of the browser

  • User interface: includes address bar, forward/back buttons, bookmark menu, etc
  • Browser engine: Transmits instructions between the user interface and the rendering engine
  • The rendering engine, also known as the rendering engine, is also known as the UI thread in terms of threads, which is the core part, So is also known as the browser kernel
  • GPU: Used to improve the web browsing experience
  • Plugins: One plugin for one process (third-party plugin process)

There are three threads inside the rendering engine that we care about

  • Networking: Used for network calls, such as HTTP requests
  • Javascript interpreter: Used to parse and execute Javascript code
  • UI Backend

Where the JS thread and UI thread are mutually exclusive,

If the UI is still rendering while JS is executing, the UI thread will queue up the changes and continue rendering when js threads are idle

There are other threads, and these are the ones we use to distribute asynchronous tasks

  • The browser event triggers the thread
  • Timing trigger thread
  • Asynchronous HTTP request threads

— End —