preface
Event Loop
That is, the event loop refers to a browser or Node to solve the js single-threaded run will not block a mechanism, that is, we often use the principle of asynchronous in order to achieve the concept of asynchronous JS- Process: The smallest unit of work assigned by a computer
- Thread: A process contains multiple threads
EventLoop
So what we’re dealing with is we’re going to call asynchronous methods when we execute js and how do those methods schedule execution
Browser processes
- Each TAB page is a process.
- Browsers also have a main process (user interface)
- Network processes (processing requests)
- GPU process 3D drawing
- Processes of third-party plug-ins
Rendering process
Each TAB page has a rendering process (browser kernel)
Rendering process
- Contains multiple threads
- GUI rendering threads are used to render pages
- JS engine thread and page rendering are mutually exclusive
- The event triggers a thread-independent thread
EventLoop
- The event
click
setTimeout
ajax
It’s also a separate thread
process
- The following chart
- Macro tasks such as:
setTimeout setInterval postMessage MessageChannel setImmediate...
- Microtasks such as:
promise.then mutationObserver
*Js executes from top to bottom*The encountered function creates an execution context and puts it on the execution stack*Asynchronous events may occur during execution (internal browser Api calls such as:`setTimeout`.`ajax`...).*When we execute the context stack, we may have an API (e.g`setTimeout`) Execution is complete or time is up*Is maintained to an event queue (first in, first out)*Constantly scanning the queue to pull tasks out of the queue and put them on the context stack*The event loop thread is the thread that does this specifically to check if the current stack is empty if it's empty from the event queue** one to perform **(e.g.,'setTimeout(macro task)')
*There are also some tasks when the code executes'promise.then(micro-task)'As an example*A separate microtask queue is created each time a macro task is executed (first in, first out)*The browser detects whether to re-render the browser after the microtask has been executed with a refresh rate of about 16.6ms*Browsers won't render anything less than that*Each loop executes one macro task at a time and emptying the corresponding microtask queue*Microtasks generated during execution will be cleared directly in this round*At the end of each loop, you're going to see if you want to render if you need to renderCopy the code
The sample
Microtasks and GUI rendering
// Does the background color change from red to yellow
// Execute stack [console.log(1) console.log(3)]
// microtask queue [promise.then]
// Clear microtasks after executing macro tasks
// Render the page from red to yellow
// log: 1 3 2
document.body.style.background = 'red';
console.log(1)
Promise.resolve().then(() = >{
console.log(2)
document.body.style.background = 'yellow';
})
console.log(3);
Copy the code
Event task
<button id="button">Events button</button>
Copy the code
/ / the first
// What is the output of button.click() without clicking the button
// The current two events are executed in the execution stack
// execute stack ['click1' 'click2']
[promise.then1 promise.then2]
// log: 'click1' 'click2' 'c1-micro-task1' 'c2-micro-task2'
button.addEventListener('click'.() = >{ / / 1
console.log('click1');
Promise.resolve().then(() = >console.log('c1-micro-task1'))
})
button.addEventListener('click'.() = >{ / / 2
console.log('click2');
Promise.resolve().then(() = >console.log('c2-micro-task2'))
})
button.click();
Copy the code
/ / the second
// What is the output of the current button click
// Let's see what happens
// The event loop thread does this specifically to check if the stack is empty. If it is empty, it can pull ** from the event queue to execute **
// Execute one by one on the stack
// Macro queue [addEventListener1 addEventListener2]
// Take out addEventListener1 and empty the microtask queue [promise.then1]
// Take out addEventListener2 again and empty the microtask queue [promise.then2]
// log: 'click1' 'c1-micro-task1' 'click2' 'c2-micro-task2'
button.addEventListener('click'.() = >{ / / 1
console.log('click1');
Promise.resolve().then(() = >console.log('c1-micro-task1'))
})
button.addEventListener('click'.() = >{ / / 2
console.log('click2');
Promise.resolve().then(() = >console.log('c2-micro-task2'))})Copy the code
Timer task
// Stack execution has timer time to put into macro task queue [setTimeout2]
// The stack completes execution
// Then empty the microtask queue [promise.then1]
// The microtask has timer time until it is put into the macro task queue [setTimeout2 setTimeout1]
// The last macro task is executed
// log: Promise1 setTimeout2 Promise2 setTimeout1
Promise.resolve().then(() = > { / / 1
console.log('Promise1')
setTimeout(() = > {
console.log('setTimeout1')},0);
})
setTimeout(() = > { / / 2
console.log('setTimeout2');
Promise.resolve().then(() = > {
console.log('Promise2')})},0);
Copy the code
An interesting interview question
await
Will suspendasync
The code behind the function- To perform first
async
Synchronization code outside of a function - if
await
isPromise
object - Waiting for the
Promise
The state of the object isstatus = 'FULFILLED'
- Then put the
resolve
As the parameter ofawait
After the result of the operation on the expression is returned - Carry on
async
The code behind the function
// log: 1 6 2 3 8 7 4 5
console.log(1);
async function async () {
console.log(2);
await console.log(3);
console.log(4)}setTimeout(() = > {
console.log(5);
}, 0);
const promise = new Promise((resolve, reject) = > {
console.log(6);
resolve(7)
})
promise.then(res= > {
console.log(res)
})
async(a);console.log(8);
Copy the code