zl程序教程

您现在的位置是:首页 >  Python

当前栏目

eventLoop事件循环机制

2023-02-25 18:27:43 时间

打个比喻

银行柜台就一个:

普通客户 - 宏任务

vip客户 - 微任务

普通客户(宏任务)依次排队,vip客户(微任务)到了之后直接插到当前正在办理的普通客户后面

大白话

JavaScript 是单线程执行的,也就是无法同时执行多段代码,当某一段代码正在执行的时候,所有后续的任务都必须等待,形成一个队列,一旦当前任务执行完毕,再从队列中取出下一个任务。这也常被称为 “阻塞式执行”。所以一次鼠标点击,或是计时器到达时间点,或是 Ajax 请求完成触发了回调函数,这些事件处理程序或回调函数都不会立即运行,而是立即排队,一旦线程有空闲就执行。假如当前 JavaScript 进程正在执行一段很耗时的代码,此时发生了一次鼠标点击,那么事件处理程序就被阻塞,用户也无法立即看到反馈,事件处理程序会被放入任务队列,直到前面的代码结束以后才会开始执行。如果代码中设定了一个 setTimeout,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但不是立即执行,仍然要等待前面代码执行完毕。所以setTimeout 并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。

理解eventloop

因为js是单线程,所以有一套固定的执行顺序,也就是eventloop。

eventloop分为同步任务和异步任务。同步任务执行完才会执行异步任务。

异步任务分又为宏任务和微任务。

宏任务有script标签、定时器。

微任务有promise.then/catch。

eventloop过程简述:js从第一个宏任务(script标签)开始执行,会先把同步代码都执行完,中途遇到微任务先加入微队列,宏任务加入宏队列。等同步代码清完,先清空微队列。再去宏队列开启一个新的宏任务。循环往复

(宏1 → 宏1同步 → 所有微 → 宏2 → 宏2同步 → 所有微 → 宏3同步···)

举个栗子

1
2<script>  //script标签属于宏任务,会开启第一个宏任务
3
4console.log("1") //属于第一个宏任务内部的同步代码,所以第一个执行
5
6setTimeout(function() { //遇到定时器,会开启第二个宏任务,所以去后面排队
7    console.log("2"); //第二个宏任务的同步代码,所以第五个执行
8},0)
9
10
11new Promise(function(resolve) {
12    console.log("3"); //属于第一个宏任务内部的同步代码,所以第二个执行
13    resolve()
14}).then(function() {
15    console.log("4"); //属于第一个宏任务内部产生的微任务,所以第四个执行
16})
17
18console.log("5"); //属于第一个宏任务内部的同步代码,所以第三个执行
19
20</script>
21

以上代码最终输出 1

3

5

4

2