Browser Event Loop

Processes and threads

JS is single-threaded execution, then what is the thread of it?

Talked about the thread, then certainly have to say about the process, in essence, the two terms are CPU work time slice a description.

It describes a process in CPU time and run commands to load and save the required context , on the applications on behalf of a program. A thread is in the process of smaller units, describes the period of time required to execute an instruction.

These concepts to get the browser, when you open a Tab page, in fact, is to create a process, a process can have multiple threads, such as rendering thread , JS engine thread , HTTP request thread and so on. When you initiate a request, in fact, it is to create a thread, after the end of the request, the thread could have been destroyed.

Mentioned above JS engine thread and rendering thread, in the JS run time may prevent UI rendering, which shows the two threads are mutually exclusive of. The reason for this is because JS can modify the DOM, if the course of implementation in JS UI thread is still working, it could lead to unsafe rendering UI. One benefit of this is actually a single-threaded, single-threaded run thanks to JS, you can reach save memory, save context switch time, no locking problems.

Execution stack

It can be considered an execution stack storage function call stack structure , following the last-out principle

For example, execute the following code:

function foo (b) {
    let a = 5
    return a * b + 10
}
function bar (x) {
    let y = 3
    return foo(x * y)
}

console.log(bar(6))

It will first perform a main function, and then execute our code, according to the principle of last-out, the function will be executed after first popped off the stack.

 

 

 

 

 

 

 

 

 

 

 

 

We can also find traces of an error in the execution stack

function foo() {
  throw new Error('error')
}
function bar() {
  foo()
}
bar()

You can clearly see an error in the function foo, foo function is called in the function bar

When we use recursion, because the function stack that can be stored is limited, once the function of storing too much and not been released, the situation stack overflow occurs.

Browser Event Loop

Through the above code, we know that when we execute JS code is actually to perform the stack into the function, then the asynchronous code encountered when how to do? In fact, when faced with the asynchronous code, it will be suspended and you need to perform when added to Task (a variety of Task) queue . Once the execution stack is empty, Event Loop will come from the Task Queue code needs to be executed and placed in the implementation of the execution stack , so that JS asynchronous or synchronous behavior in nature.

Different tasks are assigned to different sources of Task queue, the task source can be divided into micro tasks (Microtask)  and macrotask (macrotask). In ES6 specification, microtask called jobs, macrotask called task. Let's look at the following code execution sequence

console.log('script start')

async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()

setTimeout(function() {
console.log('setTimeout')
}, 0)

new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
    console.log('promise1')
})
.then(function() {
    console.log('promise2')
})

console.log('script end')
// script start -> async2 end -> Promise -> script end
// -> promise1 -> promise2 -> async1 end -> setTimeout

We look at the above code async and await execution order, when we call async1 function, the output will immediately async2 end, and the function returns a Promise , the next encounter await the time will make a thread begins execution async1 outside code, so we can all await as a let-out thread logo.

Then when the synchronization code is executed, it will go to perform all of the asynchronous code, then get back to await the position of the implementation of the returned Promise of resolve function, then it will resolve thrown micro queue, the next to carry out the following our new Promise two out of the then callback when callback after two then all finished, will return to await the return value of the location process, this time can be seen as Promise.resolve (return value) .then () then await code will be all wrapped into then callback functions, so console.log ( 'async1 end') will take precedence in setTimeout

Two code similar to the following functions async

new new Promise ((Resolve, Reject) => { 
  the console.log ( 'End async2' )
   // Promise.resolve () the micro-code into the task queue tail 
  // Resolve - insert the task queue tail again 
  resolve (Promise.resolve () ) 
}). the then (() => { 
  the console.log ( 'End Async1' ) 
})

That is, if await followed Promise , then, Async1 End to wait three tick in order to perform, then, in fact, the performance is still relatively little slow. So V8 team draws a Bug in Node 8, at the bottom of the engine three times to reduce the tick secondary tick. This practice is illegal but in fact the norm, of course, also possible to change the specification, this is a PR V8 team, has now been agreed to this approach. But from our point of view operating results browser, it did not seem to change.

Therefore Event Loop execution sequence is as follows:

  • First perform synchronization code, which belongs to the macro task
  • When finished performing all synchronization code, execution stack is empty, check whether there is need to perform asynchronous code
  • Perform all micro-tasks
  • When finished performing all micro-tasks, if necessary, will render the page
  • Then start the next round of Event Loop , execution of the macro task asynchronous code . That is setTimeout callback

So although the above code setTimeout wrote in Promise before, but because Promise belong to micro-macro task setTimeout belong to the task , so the above will be printed.

Micro tasks include: process.nextTick , Promise , MutationObserver

Macro tasks include: Script , the setTimeout , setInterval , setImmediate , the I / O , the UI Rendering

Here many people have a misunderstanding that the micro-macro task to task faster, in fact, is wrong. Because the macro tasks included , the browser will first execute a macro task , then have something asynchronous code will be executed first micro-tasks. script 

Guess you like

Origin www.cnblogs.com/jett-woo/p/12557035.html