event loop article is enough

event loop

Browser kernel is multi-threaded, Javascriptsingle-threaded.

The landlord explained prior jsasynchronous processing, just to explain a method of asynchronous processing, but for the principle of asynchronous processing is still not very understanding, this article is for threading of the browser JavaScriptto analyze operational mechanism.

1: Basic Browser

We often say that jsthe environment is a single-threaded execution, executes the code in order, but JavaScriptthey can be asynchronous, both feel there is a conflict, but essentially, if you understand the browser's event loop mechanism (event loop), it will that does not conflict.

Only browser which not only explain JavaScriptthe engine, also includes many other engines.

 
Browser mechanisms .png

Browser include:

  1. User Interface: including the address bar, forward / back buttons, bookmarks menus. In addition to the page you requested main browser window displays, each display belong to other parts of the user interface.
  2. Browser engine (browser kernel): The user interface and rendering transfer instructions between engine.
  3. The rendering engine - responsible for displaying the contents of the request. If the requested content is HTML, it is responsible for parsing HTML and CSS content, and the parsed content displayed on the screen.
  4. Networking - used for network calls, like HTTP requests. Its interface platform-independent, and provide the underlying implementation for all platforms.
  5. The rear end user interface - for drawing basic widgets, such as combo boxes and windows. Which discloses a universal interface platform-independent, using the underlying operating system's user interface method.
  6. JavaScript interpreter. For parsing and executing JavaScript code.
  7. data storage. This is the persistence layer. The browser needs to save all kinds of data on the hard disk, such as Cookie. The new HTML specification (HTML5) defines 'web database', which is a complete (but lightweight) in the browser database.

We discuss today is the interaction and communication between the browser engine (browser kernel) and JavaScript interpreter (V8 engine).

2: browser engine (browser kernel)

Browser kernel is a multi-threaded processing, which mainly includes the following several threads

  1. GUI rendering thread: Rendering page htmlelements
  2. JavaScript engine thread: page interaction and domrendering
  3. Timing trigger thread: After a certain time, to trigger a corresponding thread
  4. Event Trigger thread: When an event triggers the thread, it will put it js event queue waiting to be executed. Commonly used in asynchronous operation.
  5. Http asynchronous threads: the XMLHttpRequest after the connection is through a browser to open a new thread request, when the state change is detected, if provided with a callback, asynchronous thread state change event generated JavaScript engine into the processing queue waiting to be processed.

There are about links between them:

  1. JavaScript engine and GUI engine mutually exclusive, while not operate domwhile rendering pages
  2. JavaScript is single-threaded engine, all need to follow the event processing queue to handle the corresponding code.
  3. JavaScript engine has a function to listen for events (monitoring process), and will be continuing to check jswhether the engine main thread execution stack is empty, if empty it will pick up the thread trigger event stored in the event queue callback function to perform.

3: js engine enforcement mechanisms

Because js operating environment is single-threaded, asynchronous operation of some still need to achieve this by means of the browser host. FIG herein to describe a simple jsprocess when running. The main use of the browser js engine thread and event-triggered thread, sometimes open network services and the timer will be used in other threads.

 
Operational flow chart .png

4: micro task 和 macro task

The event loop browser has to rely on the event queue, but a process than an event queue, can be divided micro taskand macro taskcommon tasks micro and macro tasks include:

micro task :

  • nextTick
  • callback
  • Promise
  • process.nextTick
  • Object.observe
  • MutationObserver

macro task:

  • setTimeout
  • setInterval
  • I / O
  • script代码块

主要部分: 事件队列在同步队列执行完后,首先会执行nextTick,等nextTick执行完成后,然后会先执行micro task, 等micro task队列空了之后,才会去执行macro task,如果中间添加了micro task加入了micro task队列,会继续去执行micro task队列,然后再回到macro task队列。js引擎存在monitoring process进程, 会不停的监听task queue

它们的细节可以参考Tasks和Microtasks

5:event loop和宏任务、微任务

一段代码块就是一个宏任务。所有一般执行代码块的时候,也就是程序执行进入主线程了,主线程会根据不同的代码再分微任务和宏任务等待主线程执行完成后,不停地循环执行。

主线程(宏任务) => 微任务 => 宏任务 => 主线程

下图是一个简易的时间循环:

 
event loop.png

6: 简易的event loop

console.log('start') Promise.resolve().then((resolve) => { console.log(1) })) console.log('end') 

大致流程:

  1. 这一个代码块相当于一个macro-task,进入主线程。
  2. 遇到同步的代码console.log('start')开始执行
  3. Promise是micro-task,把它的回调函数放入微任务Event Queue中
  4. 遇到console.log开始执行,执行完后,这个代码块宏任务完成,js监听进程发现主线程空了,就会去寻找微任务。
  5. 去微任务Event Queue找到Primise的回调函数,执行。

图解浏览器内部执行:

 
运行全图.png

7:复杂的分析

这里我们通过2个复杂的代码来检验是否已经基本了解了事件循环的机制:

// 来至于谷友的一到面试题
<script>
async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { console.log('async2'); } console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); async1(); new Promise(function(resolve) { console.log('promise1'); resolve(); }).then(function() { console.log('promise2'); }); console.log('script end'); </script> 
  1. 整个代码块作为一个宏任务,进入主线程

  2. 看到函数申明但没有执行,遇到函数console.log执行,输出script start

  3. 遇到setTimeout() ,把它的回调函数放入宏任务(setTimeout1)。

    宏任务 微任务
    setTimeout1  
  4. 遇到执行async1(), 进入async的执行上下文之后,遇到console.log输出async1 start

  5. 然后遇到await async2(),由于()的优先级高,所有先执行async2(),进入async2()的执行上下文。

  6. 看到console.log输出async2,之后没有返回值,结束函数,返回undefined,返回async1的执行上下文的await undefined,由于async函数使用await后得语句会被放入一个回调函数中,所以把下面的放入微任务中。

    宏任务 微任务
    setTimeout1 async1=> awati 后面的语句
  7. 结束async1,返回全局上下文,遇到Promise构造函数,里面的函数立马执行, 输出promise1, 之后的回调函数进入微任务

    宏任务 微任务
    setTimeout1 async1=> awati 后面的语句
      new Promise() => 后的then
  8. 执行完Promise(),遇到console.log,输出script end,这里一个宏任务代码块执行完毕。

  9. 在主线程执行的过程中,事件触发线程会一直监听异步事件,当异步事件处理完成后,把它的回调函数放入事件队列,等待执行。

  10. 主线程现在空闲下来后,执行事件队列中的微任务,然后继续向下执行,遇到new Promise()后面的回调函数,执行代码,输出promise2(这里2个微任务的优先级,promise高于async)。

  11. 看到async1await后面的回调函数,执行代码,输出async1 end

    宏任务 微任务
    setTimeout1
  12. 此时微任务中的队列为空,开始执行队列中的宏任务,进入一个新的代码块。遇到console.log,输出setTimeout

  13. 执行完成,最后结果为

```javascript
script start => async1 start => async2 => promise1 => script end => promise2 => async1 end => setTimeout ``` 

8:总结

  1. JavaScript运行环境是单线程,不管什么代码,什么框架的异步代码,都是利用宿主对象(Node,浏览器)的其他线程来通过事件循环机制实现
  2. 我们一般说的运行和执行是不一样的,JavaScript的运行环境是JavaScript解析引擎,执行环境比如node,浏览器。
  3. JavaScript解析引擎会监听事件循环机制,把异步任务放入事件队列。

链接参考:

这一次,彻底弄懂 JavaScript 执行机制

图形制作软件

从Promise来看JavaScript中的Event Loop、Tasks和Microtasks

Js 的多宿主时代

Guess you like

Origin www.cnblogs.com/zhilin/p/11411599.html