preface
Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money. An Event Loop is an Event Loop that allows browsers or Nodes to run without blocking.
Before we can learn Event Loop, we need to solve a few problems:
- What are synchronous and asynchronous?
JavaScript
Is a single-threaded language, so how do you implement asynchrony?- What is the order in which synchronous and asynchronous tasks are executed?
- Do asynchronous tasks have a priority?
Synchronous and asynchronous
Synchronization and asynchrony in the computer world are the opposite of synchronization and asynchrony in our real world. In reality, synchronization means simultaneous, especially simultaneous, such as eating snacks while watching a football match. Asynchronous means not at the same time. But there are certain differences between computer and reality.
Take a chestnut
The weather was cold, I just woke up in the morning and wanted to drink some hot water to warm myself up, but I got up from morning to night every day. I was so tired that I went to sleep when I came back at night. There was no boiling water.
It was too cold in the morning now, so I could not help lying in the bed for a while, and the cleaning time was too tight to wait for the water to boil, so I took advantage of this to wash and clean up myself. After washing, the water opened, drink warm hot water, comfortable ah!
Comfortable end, open the new 996 day, working people set out!
Boiling water and washing are done at the same time. This is asynchrony in computers.
Synchronization in a computer is a continuous action that blocks the next step until the last one is complete. You can’t drink warm hot water until it boils.
Can a single thread be asynchronous?
JavaScript is indeed a single-threaded language, but the browser UI is multithreaded, and asynchronous tasks are implemented using the browser’s thread and JavaScript’s execution mechanism. For example, setTimeout is implemented with the help of a browser timer that triggers a thread’s timing.
Browser thread
GUI
The render thread- Draw pages, parse HTML, CSS, build DOM trees and so on
- Page redrawing and rearrangement
- Mutually exclusive with JS engine (JS engine blocks page refresh)
JS
Engine threads- Js script code execution
- Responsible for executing prepared events, such as timer termination or asynchronous request return with success
- Mutually exclusive with GUI rendering threads
- Event trigger thread
- When the corresponding event meets the trigger condition, the event is added to the end of the JS task queue
- Multiple events are queued to join the task queue
- Timer trigger thread
- Timer events that execute asynchrony: setTimeout, setInterval, etc
- Browser timing is done by this thread, and the event is added to the end of the task queue
HTTP
Request thread- Responsible for asynchronous requests
- When listening for an asynchronous request status change, the thread adds the callback function to the end of the task queue if it exists
Synchronous and asynchronous execution sequence
JavaScript
Tasks are divided into synchronous tasks and asynchronous tasks. Synchronous tasks enter the main line, and asynchronous tasks enter firstEvent Table
Register the callback function.- When asynchronous taskTrigger condition satisfiedTo change the callback function from
Event Table
Push theEvent Queue
In the. - When the synchronization task in the main thread is complete, the system will go
Event Queue
Read the asynchronous callback function in. - Whenever the main line is open, it’s there
Event Queue
The process of reading fetch calls is calledEvent Loop
.
Take a chestnut
- SetTimeout (cb, 1000) : After 1000ms, the CB will be added to the Event Queue.
- Ajax (request condition, CB). When the HTTP request is sent successfully, CB is pressed into the Event Queue.
EventLoop executes the process
Event LoopThe execution process is as follows:
Let’s take a look at an example to familiarize ourselves with the process.
// The print result of the following code?
// Prints first for the synchronization task
console.log("first");
setTimeout(() = > {
// the asynchronous task is pressed to the Event Table for 4ms. Then the cb task is pressed to the Event Queue
console.log("second");
},0)
// Prints last for the synchronization task
console.log("last");
// Read Event Queue prints second
Copy the code
Common Asynchronous Tasks
DOM
The eventAJAX
request- The timer
setTimeout
andsetlnterval
ES6
thePromise
Priority of asynchronous tasks
Here’s another example:
setTimeout(() = > {
console.log(1);
}, 1000)
new Promise(function(resolve){
console.log(2);
for(var i = 0; i < 10000; i++){
i == 99 && resolve();
}
}).then(function(){
console.log(3)});console.log(4)
Copy the code
Following the above learning: you can easily get the printed result of the case: 2,4,1,3.
The Promise defines the part as synchronous and the callback part as asynchronous
Running the case code on the console returns a somewhat surprising result:
When I saw this result, my first impression was that the setTimeout function 1s fired too slowly and it joined the Event Queue later than promise.then
So I changed the setTimeout callback time to 0(the browser’s minimum trigger time is 4ms), but the result is still changed.
This means that asynchronous tasks in JavaScript have priority.
Macro and micro tasks
In addition to broadly dividing tasks into synchronous and asynchronous tasks, JavaScript also makes a more detailed division of asynchronous tasks. Asynchronous tasks are further divided into micro tasks and macro tasks.
history traversal
Task (h5
History operations)process.nextTick
(nodejs
An asynchronous operation in.MutationObserver
(h5
It was added to the inside for listeningDOM
Node changing)
Macro tasks and micro tasks have their own Event queues, namely macro task queues and micro task queues.
Event Loop Indicates the execution process
After learning about macro tasks and micro tasks, let’s learn the execution sequence of macro tasks and micro tasks.
- The code starts executing, creating a global call stack,
script
Execute as a macro task - Procedure Synchronous tasks are executed immediately. Asynchronous tasks are registered to the microtask queue and macro task queue respectively based on the type of asynchronous tasks
- After the synchronization task is complete, view the microtask queue
- If there are microtasks, all the microtask queues will be executed (including the new microtasks generated during the execution of the microtasks).
- If no microtask exists, view the macro task queue and execute the first macro task. After the macro task is executed, view the microtask queue and repeat the preceding steps until the macro task queue is empty
Update the sequence diagram for the Event Loop:
conclusion
On the basis of the above learning, re-analyze the current case:
setTimeout(() = > {
console.log(1);
}, 1000)
new Promise(function(resolve){
console.log(2);
for(var i = 0; i < 10000; i++){
i == 99 && resolve();
}
}).then(function(){
console.log(3)});console.log(4)
Copy the code
The analysis process is shown in the figure below:
The interview questions
At the end of the article, there are some classic interview questions to test your knowledge of Event Loop.
Subject to a
console.log('script start');
setTimeout(() = > {
console.log('time1');
}, 1 * 2000);
Promise.resolve()
.then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
async function foo() {
await bar()
console.log('async1 end')
}
foo()
async function errorFunc () {
try {
await Promise.reject('error!!! ')}catch(e) {
console.log(e)
}
console.log('async1');
return Promise.resolve('async1 success')
}
errorFunc().then(res= > console.log(res))
function bar() {
console.log('async2 end')}console.log('script end');
Copy the code
Topic 2
setTimeout(() = > {
console.log(1)},0)
const P = new Promise((resolve, reject) = > {
console.log(2)
setTimeout(() = > {
resolve()
console.log(3)},0)
})
P.then(() = > {
console.log(4)})console.log(5)
Copy the code
The title three
var p1 = new Promise(function(resolve, reject){
resolve("2")})setTimeout(function(){
console.log("1")},10)
p1.then(function(value){
console.log(value)
})
setTimeout(function(){
console.log("3")},0)
Copy the code