JS的事件执行机制
靡不有初,鲜克有终
不积跬步无以至千里
1、为什么js是单线程?
js
作为主要运行在浏览器的脚本语言,js
主要用途之一是操作DOM
。
假设如果js
同时有两个线程,同时对同一个DOM
进行操作,这时浏览器应该听哪个线程的,如何判断优先级?
为了避免这种问题,js
必须是一门单线程语言,并且在未来这个特点也不会改变。
2、js执行机制
既然js
是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js
任务也要一个一个顺序执行。
如果一个任务耗时过长,那么后一个任务也必须等着。
那么问题来了,假如我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一直卡着直到图片完全显示出来?
因此聪明的程序员将任务分为两类:
- 同步任务
- 异步任务
当我们打开网站时,网页的渲染过程就是一大堆同步任务,比如页面骨架和页面元素的渲染;
而像加载图片音乐之类占用资源大耗时久的任务,就是异步任务。
直接上图:
导图要表达的内容用文字来表述的话:
- 同步和异步任务分别进入不同的执行"场所",同步的直接进入主线程,异步的进入
Event Table
并注册函数; - 当指定的事情完成时,
Event Table
(事件列表)会将这个函数移入Event Queue
(事件队列); - 主线程内的任务执行完毕为空,会去
Event Queue
读取对应的函数,进入主线程执行; - 上述过程会不断重复,也就是常说的
Event Loop
(事件循环)。
我们不禁要问了,那怎么知道主线程执行栈为空啊?(不用你管)
js
引擎存在monitoring process
进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue
那里检查是否有等待被调用的函数。
3、异步任务的宏与微
异步任务分为 宏任务(macrotask) 与 微任务 (microtask) ;
不同的API注册的任务会依次进入自身对应的队列中,然后等待 Event Loop
将它们依次压入执行栈中执行。
4、Event Loop(事件循环)
Event Loop
(事件循环)中,每一次循环称为 tick
, 每一次tick
的任务如下:
- 执行栈选择最先进入队列的宏任务(通常是
script
整体代码),如果有则执行 - 检查是否存在
Microtask
,如果存在则不停的执行,直至清空microtask
队列 - 更新
render
(每一次事件循环,浏览器都可能会去更新渲染) - 重复以上步骤
宏任务A > 所有微任务 > 宏任务B,如下图所示:
从上图我们可以看出:
1、将所有任务看成两个队列:执行队列与事件队列。
2、执行队列是同步的,事件队列是异步的,宏任务放入事件列表,微任务放入执行队列之后,事件队列之前。
3、当执行完同步代码之后,就会执行位于执行列表之后的微任务,然后再执行事件列表中的宏任务
5、举个栗子
setTimeout(function () {
console.log(1)
})
new Promise(function (resolve, reject) {
console.log(2)
resolve(3)
}).then(function (val) {
console.log(val) // 微任务1
})
new Promise(function (resolve, reject) {
console.log(4)
resolve(5)
}).then(function (val) {
console.log(val) // 微任务2
})
console.log(6)
解析一下:
第一步:宏任务A
(直接整体js代码就是第一个宏任务)
1、script
中的同步代码依次执行
2、第一个new Promise
中的console.log(2)
,得到2
3、第二个new Promise
中的console.log(4)
,得到4
4、外面的script
同步代码console.log(6)
,得到6
此次宏任务执行完毕;
第二步:所有可执行的微任务
1、then
后面的属于Promise
微任务,全部依次执行,得到3, 5
第三步:宏任务B
1、执行新的宏任务,得到1
最后,可以很轻松猜出或者说是写出正确答案:2,4,6,3,5,1
6、总结:
1、js
主要用途之一是操作DOM
,所以是一定也必须是单线程;
2、js
执行机制分为同步任务和异步任务;
3、异步任务分为 宏任务(macrotask) 与 微任务 (microtask);
4、Event Loop
(事件循环)的执行顺序:
执行同步代码 ---> 所有微任务 ---> 宏任务A ---> 所有 新产生的 微任务 ---> 宏任务B
执行流程如图:
此文章仅用于自己的理解记忆,参考的文章已经写得非常详细了,
参考链接:
转载自:https://juejin.cn/post/7038806892587515911