原文地址: https://qianduan.shop/blogs/d...

本文将简述浏览器中的js事件循环机制,帮忙咱们了解浏览器环境js代码是如何运行的。

Javascript的一大特点是单线程,也就意味着同一时间他只能做一件事。事件循环(Event Loop)是为了协调事件,用户交互,UI渲染,网络解决等行为,避免线程阻塞而诞生的。

浏览器事件循环

1.宏工作(Macro Task)和微工作(Micro Task)

浏览器中js事件循环的异步队列有两种:macro(宏工作)队列和 micro(微工作)队列。宏工作队列能够有多个,微工作队列只有一个。

常见的宏工作:定时器(setTimeout,setInterval)、script(整体代码)、 I/O 操作、UI渲染等。

常见的微工作: Promise.then(Promise的回调办法)、MutationObserver(html5新个性) 等。

2.事件循环过程解析

一个残缺的事件循环过程能够概括为以下阶段:

[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-NmXzcMT0-1637111445594)(/static/images/event_loop.png)]

① 刚开始执行栈空,咱们能够把执行栈认为是一个存储函数调用的栈构造,遵循先进后出的准则。微工作队列为空,宏工作队列里有且只有一个 script 脚本(整体代码)。

② 全局上下文(script 标签)被推入执行栈,同步代码执行。在执行的过程中,会判断是同步工作还是异步工作,通过对一些接口的调用,能够产生新的宏工作与微工作,别离被推入各自的工作队列里。同步代码执行完了,script 脚本会被移出宏工作队列,这个过程实质上是队列的宏工作的执行和出队的过程。

③ 上一步咱们出队的是一个宏工作,这一步咱们解决的是微工作。但须要留神的是:每执行完一个宏工作就会去检测微工作队列里是否有待解决的微工作,如果有,就会全副顺次执行并清空队列;如果没有,就执行下个宏工作。

执行渲染操作,更新界面

⑤ 查看是否存在 Web worker 工作,如果有,则对其进行解决

⑥ 上述过程周而复始,直到两个队列都清空

简略来说:

当一个宏工作执行实现之后,会查看是否有微工作队列。如果有,先执行微工作队列中的所有工作,如果没有,会读取宏工作队列中最靠前的一个,执行宏工作的过程中,遇到微工作,顺次退出微工作队列。栈空后,再次读取微工作队列里的工作,如此循环。

举个例子:

Promise.resolve().then(()=>{  console.log('Promise 1')  ;  setTimeout(()=>{    console.log('setTimeout 1');  },0);});setTimeout(()=>{  console.log('setTimeout 2');  Promise.resolve().then(()=>{    console.log('Promise 2');  })},0);

输入后果:Promise 1, setTimeout 2, promise 2, setTimeout 1

例子解析:

① 全局同步代码(整个代码块)执行(这属于宏工作),执行结束(上述代码产生了一个宏工作setTimeout 2 和一个微工作Promise 1),查看并执行微工作队列,输入Promise 1,同时会生成一个宏工作 setTimeout 1。

② 而后去查看宏工作队列,宏工作 setTimeout 2 在 setTimeout 1 之前,先执行宏工作 setTimeout 2,输入 setTimeout 2。

③ 在执行宏工作setTimeout 2时会生成微工作Promise 2 ,放入微工作队列中,接着先去清空微工作队列中的所有工作,输入 Promise 2。

④ 清空完微工作队列中的所有工作后,就又会去宏工作队列取一个,这回执行的是 setTimeout 1。