preface

  • Event LoopThat 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
  • EventLoopSo 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 processEach 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 threadEventLoop
  • The eventclick setTimeout ajaxIt’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

  • awaitWill suspendasyncThe code behind the function
  • To perform firstasyncSynchronization code outside of a function
  • ifawaitisPromiseobject
  • Waiting for thePromiseThe state of the object isstatus = 'FULFILLED'
  • Then put theresolveAs the parameter ofawaitAfter the result of the operation on the expression is returned
  • Carry onasyncThe 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

After the