[Summary] Synchronization, asynchronous, macro task, micro task and EventLoop in JS

synchronous and asynchronous

Presumably everyone has heard that JavaScript is single-threaded, so how does this language come about synchronous and asynchronous? This involves a very important point. Although JavaScript is single-threaded, browsers have multiple threads. For a single page, not only threads are responsible for processing JavaScript code, but also threads responsible for network requests, responsible for monitoring user operations After these things are processed , they will enter the task queue (will be discussed in detail later) to notify the main thread, that is, the thread that executes the JavaScript code, which reflects the asynchronous characteristics.
For the sake of simplicity, JavaScript itself does not provide an API to enable threads, so it is okay to say that JavaScript is single-threaded, but don’t think that this means that the entire page is only running on the JavaScript thread, which is unrealistic of

Macrotasks and Microtasks

Following the above, all tasks are divided into two types: synchronous and asynchronous . Synchronous means that the main thread that can get the result soon will execute it immediately when it encounters a synchronous task, without delaying it later, while the asynchronous situation is more complicated.
Asynchronous tasks are divided into two types: macro tasks and micro tasks . The macro tasks will be processed after the micro tasks are processed, and whether the asynchronous task is judged as macro or micro depends on the official definition. Common classifications are as follows:

Task type
script (overall code) macro task
User interaction macro task
I/O operation macro task
setTimeout macro task
setInterval macro task
Promise.then micro task
catch、finally micro task

task queue

When the main thread encounters an asynchronous task, the background will allocate a thread for processing, and put its callback function into the task queue after processing. This is the composition of the task queue. Note that the callback function of the asynchronous task is pushed into the task queue, not the asynchronous task itself.

EventLoop

With the above concepts, you can easily understand what EventLoop is all about.
The JavaScript engine will continuously poll the task queue, take out the first added macro task, put it into the call stack, and then start executing the code in it. The engine will execute all synchronous codes from top to bottom. When it encounters a micro task, it will put Execute at the end, and when encountering a macro task, it will be placed at the end of the task queue to wait for execution. (Here is just a brief description of the EventLoop process, and the specific implementation will be more complicated)

See the picture below:

Promise

We know that the emergence of Promise is to save the situation of callback hell. But in my opinion, it does not change the essence of callback hell. Everyone sends Ajax requests. After getting the results, the callback function will be placed in the task queue for execution. It's just that before we wrote all the subsequent requests in the first callback function, which made it look like an onion, nested layer by layer, while Promise wrote the request and callback function separately, and each then can be rewritten Return a Promise to make it look like a chain

//回调地狱
ajax(url, () => {
    
    
    //业务代码
    ajax(url1, () => {
    
    
        //业务代码
        ajax(url2, () => {
    
    
            //业务代码
        })
    })
})
//Promise版本
ajax(url)
    .then(res => {
    
    
        //业务代码
    })
    .then(res => {
    
    
        //业务代码
    })
    .then(res => {
    
    
    	//业务代码
    });

async and await

Await is actually some encapsulation of Promise. Using await will look more beautiful than using Promise, just like synchronous code, as follows:

//async、await版本
async function foo(){
    
    
	let res1 = await ajax1(url)
	let res2 = await ajax2(res2)
	return res2
}

The code before await can be understood as the code passed in by new Promise, while the code after that is the callback in Promise.then.
See the following example:

setTimeout(_=>{
    
    
    console.log('10')
},0)
async function foo(){
    
    
    console.log('2')
    let msg =  await new Promise((res,rej)=>{
    
    
        console.log('3')
        res('9')
        console.log('4')
    })
    console.log('6')
    await new Promise((resolve, reject) => {
    
    
        console.log('7')
        resolve('000')
        console.log('8')
    })
    return msg
}
console.log('1')
foo().then(data => console.log(data)).catch(err=> console.log(err))
console.log('5')

The correct output word order is output according to the size of the number.

Guess you like

Origin blog.csdn.net/weixin_55658418/article/details/128822730