JS事件循环
事件循环
事件循环概念: 在JavaScript中的事件循环简单理解就是js引擎的状态无限转换(等待任务=> 执行任务 => 进入休眠 => 等待任务)
当我们从外部引入一个js文件时,js引擎会先对文件进行加载;加载完成之后执行的一个任务,然后进入休眠状态等待下一个任务下发继续执行…
如果有setTimeOut任务(异步)时会有什么样的事情发生呢?
从时间循环的概念我们可以看出,JavaScript在执行时会形成一个队列,先进入队列的任务会率先执行,后进入的只能等待前面的任务执行完毕之后在执行。这个队列被称之为 宏任务队列
可是我们都用过setTimeOut,从它的语法和作用我们可以得出它的基本工作流程:
- 等待ms
- 执行回调
可是在等待的过程中其他的任务不可能等到setTimeOut回调执行之后在进行,拿这种情况js是如何处理的?
-
首先js引擎会在定时器创建时在主线程之外额外创建一个线程用于存储异步执行的任务,和宏任务队列一样先进入先执行。这个额外创建的任务队列被称为 微任务队列
-
当事件循环的微任务队列不为空时:选择第一个进入微任务队列的任务,设置当前执行的微任务为选择的微任务;执行完毕后将选中的微任务移除队列;周而复始直至微任务队列为空。
需要注意的是:当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件, 然后再去宏任务队列中取出一个 事件。同一次事件循环中, 微任务永远在宏任务之前执行。
宏任务和微任务
微任务是我们自己的代码,它们通常是由promise创建的:对(.then/.catch/.finally)所创建的代码会产生微任务。微任务也被用于 “await” 的幕后,因为它是promise的另一种处理形式。
每个宏任务之后,引擎会立即执行微任务队列中的所有任务,然后再执行其他的宏任务,或渲染,或进行其他任何操作。
我们可以分析以下代码的执行流程:
setTimeout(() => alert("timeout"));
Promise.resolve()
.then(() => alert("promise"));
alert("code");
执行流程如下:
- 首先弹出code 因为它是处于宏任务队列中的
- 然后执行promise 因为它是一个微任务,只有微任务执行完毕之后才会执行下一个宏任务
- 因此最后执行的就是timeout