1. Why is JS single threaded
Js is run in the browser’s scripting language, because its are often involved in operating the dom, if it is multi-threaded, if one thread to modify the dom, another thread to delete the dom, the browser will not know which one to perform first operation, so js will in accordance with a mission to perform a task, the task is how to arrange
2. Why are JS tasks classified into synchronous and asynchronous tasks
Imagine if js tasks were synchronous, what would happen if you encountered timer, network request, etc., tasks that require delayed callback function execution? The page crashes and pauses to wait for the code that takes time to execute. Based on this, asynchronous tasks are introduced, and each asynchronous task must be introduced
- Synchronization task: A synchronization task can be performed immediately without waiting, such as Console
- Asynchronous tasks: Asynchronous tasks need to wait a certain amount of time to see the result, such as setTimeout, network request
- Example 1.
Sample one we can see both synchronization task and asynchronous tasks, so the main thread will be in the process of execution of the two timer callback function to register the asynchronous event queue, the final output 1, 2, 3, 4, but why is the second setTimeout output first, obviously can be seen in the code because the waiting time is different, However, if it is a network request, the time is not specified in advance like a timer. To solve this problem, a message queue is set up, which can also be understood as an event listener
Console. log(1) // Synchronization task setTimeout(() => {// async task console.log(4)}, 2000) setTimeout(() => {// Asynchronous task console.log(3)}, 1000) console.log(2) // Synchronization task ' 'Copy the code
3. Why is message queue set up in asynchronous task (event listener)
Event listeners can listen to the status of asynchronous tasks and put the corresponding task on an event queue if it is ready to perform a callback
- Example 1.
Example 1 assumes two network requests, and the listener listens until the second request gets a response. The second callback is executed first, so the output of this code is 1, 2, 3, 4
Console.log (1) // Synchronous task Ajax ().then(() => {// asynchronous task and assume response after 3s console.log(4)}) Ajax ().then(() => {// asynchronous task and assume response after 1s Console. log(3)}) console.log(2) // Synchronize tasksCopy the code
4. Why are macro tasks and micro tasks differentiated in the events of asynchronous tasks
If the callback of the asynchronous task is dom manipulation, but page rendering is also a task, if the DOM rendering task is placed at the end of the asynchronous task queue, then the page will also crash, so JS defines some tasks that can be queued to complete, such tasks are called micro tasks, such as DOM rendering. Promise. Then,
Each macro task is followed by a microtask, as shown in the figure below. When a piece of code is encountered, all synchronization code is executed first, and then the macro task queue is read. For example, console.log(1) and console.log(2) are executed first as synchronization tasks, and macro task 1, the first Ajax task, is executed. The event listener determines which event returns the result first and eventually puts the callback function on the main thread execution stack
- Macro tasks: HTML parsing, mouse events, keyboard events, network requests, executing main thread JS code and timer (XXX in new Promise(XXX) is synchronous code)
- Microtasks: Promise. then, DOM rendering, Async, process.nexttick
5. Here are a few examples to understand macro and micro tasks
Example 1: The result is 1, 2, and 3 because 1, 2 are synchronous tasks and 3 are asynchronous tasks
```
console.log(1)
setTimeout(() => {
console.log(3)
})
console.log(2)
```
Copy the code
Example 2: The result is 1, 2, 3, and 4. The result is that 1, 2 are synchronous tasks and 3, 4 are asynchronous tasks. The second timer executes the callback first
```
console.log(1)
setTimeout(() => {
console.log(4)
}, 2000)
setTimeout(() => {
console.log(3)
}, 1000)
console.log(2)
```
Copy the code
Example 3: Log (2) The first microtask in the macro task queue is console.log(4). The second macro task is the timer. So 4 is first injected into the execution stack
```
console.log(1)
new Promise((resolve, reject) => {
console.log(2)
resolve()
}).then(() => {
console.log(4)
})
setTimeout(() => {
console.log(5)
})
console.log(3)
```
Copy the code
Example 4: Look at the examples and think about which tasks are synchronous and which are asynchronous and which are macro and micro tasks
``` console.log(1) new Promise((resolve, Reject) => {console.log(" request about to proceed ") setTimeout(() => {console.log(" request received ") resolve()}, 1000) }).then(() => { console.log(3) }) setTimeout(() => { console.log(4) }, 2000) console.log(2) // Result 1 Request about to proceed 2 Requested data 34Copy the code
- The following diagram Outlines the code execution process
Example 5: How does the browser handle the connection between the web request and the synchronized code
``` console.log(1) new Promise((resolve, Reject) => {console.log(" request about to proceed ") setTimeout(() => {console.log(" request received ") resolve()}, 2000) }).then(() => { console.log(3) }) setTimeout(() => { console.log(4) }, 1000) console.log(2) // The only difference from the previous example is that the timer is set differentlyCopy the code
Example ⑥ : This example requires some knowledge of ES6. Async is the same as Promise
Console. log('script start') async function async1() {// First promise await async2() console.log('async1 end')} Function async2() {console.log('async2 end')} setTimeout(function() {// first timer console.log('setTimeout')}) async1() New Promise(resolve => {// second Promise console.log('promise1') resolve()}). Then (function() {console.log('promise2')). }). Then (function() {console.log('promise4')}) new Promise(resolve => {// third Promise console.log('promise4')) SetTimeout (()=>{// second timer resolve()})}). Then (function() {console.log('promise5')}). Then (function() {console.log('promise5')}). Console. log('promise6')}) console.log('script end') // Execution result // script start async2 end promise1 promise4 script end async1 end promise2 promise3 setTimeout promise5 promise6 ```Copy the code
View the execution of the entire JS code as macro task 1, so you can understand how the first microtask queue is generated
This example combines the promise feature with this to point to the problem
``` { var obj = { A: function A() { console.log(this.A) }, B: () => { console.log(this.B) }, C:()=> { console.log(this.C) }, D: () => { console.log(this.D) }, E: 'E', F: 'F' } } var A = 'A', B = 'B'; const C = 'C', D = 'D'; function test() { obj.A(); // Must access the current instance of A, Resolve ().then() => {obj.c.bind (obj)() // C is for arrow and bind will call undefined, Return promise.reject ()}).then(obj.d).catch(() => {console.log(obj.e) // print E}).then(() => {console.log(obj.f) // print F})} test(); // function A undefined E F B ```Copy the code
6. Summarize the JS operation mechanism
Synchronization code all line up on the main thread of execution, asynchronous task queue is the listener regulation, each asynchronous task has callback and there is a small task queue, there is no corresponding micro task is the empty can, js endured the secret mechanism is explained js, I feel more fit their own understanding, the following figure show
If there is any misunderstanding above, I hope to point out and learn from each other