Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
This article is the front-end of learning small wisdom of learning notes, as well as some understanding of macro tasks and micro tasks. Juejin. Im/post / 5 d8020…
π JS is a single-threaded programming language, which means that only one thing can be done at a time, meaning that the JS engine can only process one statement in one thread at a time. I think you all know that.
Single-threading simplifies programming code, but it also means that you can block the main thread for a long time, such as network requests. Request some data from the API, and depending on the situation, the server takes some time to process the request, blocking the main thread and leaving the page unresponsive for a long time. This introduces asynchrony.
1. Call stack
Call stack this thing, personal understanding is like building a house to build a wall feeling, at the beginning of the brick 𧱠are pressed in the following, personal understanding is so last in first out, also often said LIFO; Let’s look at the following code:
const two = () = > {
console.log('I was the second to finish.');
}
const one = () = > {
console.log('I'll finish first.');
two();
console.log('I am the last π±');
}
one();
Copy the code
- When executing this code, theTo create a
Global execution context (represented by main())
And push it to the top of the call stack. When faced with theone()
It will be pushed toThe top of the stack
. - Next,
Console. log(' I finish first ')
Be pushed to theTop of stack
; When it’s done, it pops off the stack. After that, we calltwo()
, sotwo()
Functions are pushed to the top of the stack. two
In the functionConsole. log(' I was the second to finish ')
Be pushed to theAt the top of the stack
And pops up the stack when finished.two()
The function also ends, so it pops off the stack.Console. log(' I was the last π±');
Is pushed to theTop of stack
And delete when finished. In the end,one()
The function is done, so it is removed from the stack.- The program completes its execution at this point, so the global execution context (
main()
) pops from the stack.
2. How asynchronous code is executed:
Take a look at the following code:
const mockReq = () = > {
setTimeout(() = > {
console.log("Hey, Han, this is code in asynchrony.");
}, 2000);
};
console.log('Hello, GAMEBOY! ');
mockReq ();
console.log('the end');
Copy the code
- When the code above loads in the browser,
Console. log(' Hello, GAMEBOY! ')
Is pushed onto the stack and pops off the stack when finished. Next, you will encounter pairsmockReq()
“, so push it to the top of the stack. mockReq()
In thesetTimeout()
The function is called, so it is pushed to the top of the stack.setTimeout()
There are two parameters:- The callback function
- Time in milliseconds
setTimeout()
Methods in theweb api
Start one in the environment2s
Timer. At this point,setTimeout()
Done and popped off the stack.The console. The log (" the end ")
Pushed onto the stack, executed and removed from the stack after completion.- Meanwhile, the timer has expired, and nowThe callback function inside the timer is pushed to the message queue. But it’s not going to be implemented immediately, that’s it
Event polling
The place to start.
3. Event polling:
The job of event polling is to listen to the call stack and determine if the call stack is empty.
-
Call stack:
The call stack is not empty
: Execute the contentsThe call stack is empty
: it checks the message queue to see if there are any pending callbacks waiting to execute.
In this case, the message queue contains a callback, at which point the call stack is empty. Therefore, event polling pushes the callback to the top of the stack.
Then console.log(” Hanpi, THIS is code in asynchrony “) is pushed to the top of the stack, executed and popped off the stack. At this point, the callback is complete, so it is removed from the stack and the program is finally complete.
4. Macro and micro tasks:
Event polling in the browser eventLoop, divided into
- Synchronous execution stack: The synchronization task is preferentially executed
- Asynchronous message queue: After the synchronization task is completed, the system obtains the asynchronous task from the asynchronous message queue
Synchronous execution stack
To execute
π΅Asynchronous message queue
Tasks can be divided into the following two categories:
Macro and micro tasks:
- Macro tasks: those defined first are executed first. Include:
Ajax, setTimeout, setInterval, event binding, postMessage, MessageChannel (for messaging)
- Micro tasks,
High priority and can cut in line
Not define first execute. Include:Promise then, observer, MutationObserver, setImmediate
Let’s try to understand and digest by example.
π GAME1:
setTimeout(function() {
console.log(4);
}, 0);
new Promise(function(reslove) {
console.log(1);
reslove();
}).then(function(data) {
console.log(3);
});
console.log(2);
// outputs: 1,2,3,4.
Copy the code
π GAME1 – PROGRESS:
-
Add setTimeout to the macro task pool of the asynchronous message queue
-
Then execute console.log(1) from the promise
-
Then add the promise’s. Then to the microtask pool in the asynchronous message queue
-
Log (2). After all synchronization tasks are completed, log(3) from the microtask queue.
-
After the micro task is complete, fetch the macro task and execute console.log(4).
So the order is: 1,2,3,4.
Note π’ :
π΅promise is synchronous task, promise. Then is asynchronous task ~!!
π GAME2:
setTimeout(function() {
console.log(4);
}, 0);
new Promise(function(reslove) {
console.log(1);
setTimeout(function() {
reslove("Oh, my god, MMP."); // It is important to note that reslove is not executed, console.log is executed
console.log("Your name is twelve.");
}, 0);
reslove('first');
}).then(function(data) {
console.log(data);
});
console.log(2);
// Output result:
// 1,2, first, 4, your name is twelve
Copy the code
π GAME2 – PROGRESS:
1,2, first, 4, your name is twelve, there’s no “holy shit MMP”
Some of you might be thinking, “1,2, first, 4, your name is twelve, I’m going to use the MMP.” when reslove is used, the promise state changes from pending to resolve.
The promise state changes and cannot be changed again, so reslove(‘ I’ll fuck MMP’) will not be executed.
π GAME3:
setTimeout(function() {
console.log(1);
}, 0);
new Promise(function(reslove) {
console.log(2);
reslove('p1');
new Promise(function(reslove) {
console.log(3);
setTimeout(function() {
reslove('setTimeout2');
console.log(4);
}, 0);
reslove('p2');
}).then(function(data) {
console.log(data);
});
setTimeout(function() {
reslove('setTimeout1');
console.log(5);
}, 0);
}).then(function(data) {
console.log(data);
});
console.log(6);
// Print the result:
/ / 2,3,6, p2, p1, 1, four, five
Copy the code
π GAME3 – PROGRESS:
-
The synchronization task is performed first. New Promises are all synchronization tasks, so output 2, 3, and 6
-
Microtasks can jump the queue, so p1 is not defined first and P2 is executed first
-
Then execute p1. When all the micro tasks are completed, execute macro tasks, which output 1, 4, and 5 in sequence. The state of promise cannot be changed, so setTimeout1 and setTimeout2 will not output.
π΅ Special Statement:
In the Node environment, process.nextTick takes precedence over Promise, which means that the nextTickQueue in the microtask queue is executed after the macro task ends before the Promise in the microtask is executed.