Introduction to the
Speaking of asynchrony first, we need to understand synchronous task, asynchronous task, macro task, micro task these four terms.
1. Synchronization task: A task that is queued to be executed on the main thread can be executed only after the previous task is completed.
2. Asynchronous task: An asynchronous task is executed only after it can be executed without entering the main thread.
JavaScript\color{green}{JavaScript} iS a single thread, so it is common to say that the main thread of a synchronous task sequence, triggered by the asynchronous task will be added to the main thread to execute;
Asynchronous execution works as follows:
- All synchronization tasks are executed on the main thread, forming an execution context stack
- In addition to the main thread, there is a “task queue” in which an event is placed whenever an asynchronous task has a result
- 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, enter the execution stack, and start executing
- The main thread repeats step 3
Now that we’re talking about task queues, let’s talk about two other terms, macro tasks and micro tasks.
The task queue is divided into macro tasks and micro tasks.
3. Macrotask: it is understood that the code executed on each execution stack is a macrotask (including fetching an event callback from the event queue and placing it on the execution stack each time). The main scenarios include: main code block Script, setTimeout, setInterval, etc.
4. Microtask: A task that is executed immediately after the execution of the current task. The main scenarios include Promise, process.nextTick, etc.
Node.js also provides two other “task queue” related methods: process.nextTick and setImmediate. The process.nextTick method fires the callback function at the end of the current “execution stack” — just before the next Event Loop(the main thread reads the “task queue”). That is, the task it specifies always takes place before all asynchronous tasks. The setImmediate method adds an Event to the end of the current “task queue,” meaning that the task it specifies is always executed on the next Event Loop.
Microtasks include MutationObserver, promise.then () or Reject (), other technologies developed around Promise, such as the FETCH API, V8’s garbage collection process, and Node’s unique process.nexttick.
Macro tasks include: Script, setTimeout, setInterval, setImmediate, I/O, UI Rendering
That’s about it! Here are some interview questions to consolidate it!
case
There are several interview questions below, do not know how many you can?
Subject to a
const promise1 = new Promise((resolve, reject) = > {
console.log('promise1')
})
promise1.then(() = > {
console.log(3);
});
console.log('1', promise1);
const fn = () = > (new Promise((resolve, reject) = > {
console.log(2);
resolve('success')
}))
fn().then(res= > {
console.log(res)
})
console.log('start')
Copy the code
Process analysis:
- From top to bottom, encounter first
new Promise
Executes the code in the constructorpromise1
- Then sync code 1 is executed, at this point
promise1
Has not beenresolve
orreject
So the state is stillpending
; - And then execute to
fn()
Function, enterfn
In the print2
; - encounter
resolve
Function,promise
The state of delta changes to zeroresolved
And save the results; - encounter
fn().then
This microtask, put it in the microtask queue; - Continue sequential execution, print
start
; - After the macro task is executed, check the microtask queue
promise.then
, print thesuccess
;
Results:
promise1
1 Promise {<pending>}
2
start
success
Copy the code
Topic 2
Promise.resolve().then(() = > {
console.log('promise1');
const timer2 = setTimeout(() = > {
console.log('timer2')},0)});const timer1 = setTimeout(() = > {
console.log('timer1')
Promise.resolve().then(() = > {
console.log('promise2')})},0)
console.log('start');
Copy the code
Note that the Promise is directly resolve, whereas the previous New Promise is different.
Process analysis:
- Initially the entire script is executed as the first macro task, which we mark as
Macro 1
Execute from top to bottom - encounter
Promise.resolve().then
This micromission willthen
Is added to the first microtask queue marked asMicro 1
- Encounter timer
timer1
, add it to the delay list for the next macro task, marked asMacro 2
, waiting to be executed (regardless of what is inside) - perform
Macro 1
Synchronization code instart
- First macro task
(1)
After execution, check the first microtask queue(1)
And found onepromise.then
This microtask needs to be performed - Perform print out
Micro 1
Sync code inpromise1
And then found the timertimer2
, add itMacro 2
After, mark asMacro 3
- First microtask queue
(1)
After the command is executed, perform the second macro task(2) the macro
First the synchronization code is executedtimer1
- And then I ran into
promise2
This microtask, add it to the microtask queue for this loop, and mark it asMicro 2
Macro 2
There is no synchronization code to execute in, look for the microtask queue for this loop(2) micro
And found apromise2
, the implementation of it- The second round is complete. Run
Macro 3
To print outtimer2
Results:
'start'
'promise1'
'timer1'
'promise2'
'timer2'
Copy the code
The title three
const promise1 = new Promise((resolve, reject) = > {
setTimeout(() = > {
resolve('success')},1000)})const promise2 = promise1.then(() = > {
throw new Error('error!!! ')})console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() = > {
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
Copy the code
Process analysis:
- Top to bottom, execute the first one first
new Promise
The function ofsetTimeout
Add it to the next macro task list - Jump out of the
new Promise
Met,promise1.then
This microtask, but its state is still zeropending
, it is understood that it is not executed first promise2
Is a new state for thetapending
thePromise
- Execute sync code
console.log('promise1')
, and printed outpromise1
The status ofpending
- Execute sync code
console.log('promise2')
, and printed outpromise2
The status ofpending
- When you hit the second timer, place it on the next macro task list
- The first macro task completes and no microtasks need to be executed. Therefore, the second macro task is executed
- Execute the contents of the first timer first
promise1
Change the state ofresolved
And save the result and put the previouspromise1.then
Push into the microtask queue - The timer has no other synchronization code to execute, so it executes the microtask queue of this round, i.e
promise1.then
, it throws an error and willpromise2
Is set torejected
- After the first timer is executed, the contents of the second timer are executed
- Print out the
'promise1'
And at this timepromise1
The status ofresolved
- Print out the
'promise2'
And at this timepromise2
The status ofrejected
Results:
'promise1' Promise{<pending>}
'promise2' Promise{<pending>}
test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102
'promise1' Promise{<resolved>: "success"}
'promise2' Promise{<rejected>: Error: error!!! }Copy the code
The title four
If you understand the above problem, we can do this one, and you should be able to answer it pretty quickly:
const promise1 = new Promise((resolve, reject) = > {
setTimeout(() = > {
resolve("success");
console.log("timer1");
}, 1000);
console.log("What's in promise1?");
});
const promise2 = promise1.then(() = > {
throw new Error("error!!!");
});
console.log("promise1", promise1);
console.log("promise2", promise2);
setTimeout(() = > {
console.log("timer2");
console.log("promise1", promise1);
console.log("promise2", promise2);
}, 2000);
Copy the code
Results:
'What's in promise1'
'promise1' Promise{<pending>}
'promise2' Promise{<pending>}
'timer1'
test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102
'timer2'
'promise1' Promise{<resolved>: "success"}
'promise2' Promise{<rejected>: Error: error!!! }Copy the code
Have you got all these questions? Continue to update!