题解Event Loop

参考
来源:https://www.bilibili.com/video/BV1sN411974w?p=2
细讲:

一次弄懂Event Loop(彻底解决此类面试问题) - 知乎 (zhihu.com)

Call stack(调用栈) - 术语表 | MDN (mozilla.org)

5分钟理解JS调用栈 - 知乎 (zhihu.com)

微任务、宏任务与Event-Loop - 掘金 (juejin.cn)

并发模型与事件循环 - JavaScript | MDN (mozilla.org)

1. 知识

是一种数据结构,是利用完全二叉树维护的一组数据,分为两种,一种为最大,一种为最小堆,将根节点最大叫做最大堆大根堆,根节点最小叫做最小堆小根堆

线性数据结构,相当于一维数组,有唯一后继。

在计算机科学中是限定仅在表尾进行插入删除操作的线性表。是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底最后的数据栈顶,需要读数据的时候从栈顶开始弹出数据

是只能在某一端插入删除特殊线性表

队列

特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和一样,队列是一种操作受限制的线性表。

进行插入操作的端称为队尾,进行删除操作的端称为队头。 队列中没有元素时,称为空队列

队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出FIFO—first in first out

Event Loop

Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。

所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)

  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

JavaScript中,任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务(MicroTask)。

宏任务

script全部代码、setTimeoutsetIntervalsetImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/OUI Rendering

微任务

Process.nextTick(Node独有)PromiseObject.observe(废弃)MutationObserver(具体使用方式查看这里)会加入微任务

  • 微任务会在任务队列为空的时候立即执行
  • 调用栈中加入的微任务会立即执行

JS调用栈

所有同步任务都在主线程上执行,形成一个调用栈。

  • 每调用一个函数,解释器就会把该函数添加进调用栈并开始执行。
  • 正在调用栈中执行的函数还调用了其它函数,那么新函数也将会被添加进调用栈,一旦这个函数被调用,便会立即执行。
  • 当前函数执行完毕后,解释器将其清出调用栈,继续执行当前执行环境下的剩余的代码。
  • 当分配的调用栈空间被占满时,会引发“堆栈溢出”错误。

任务队列

主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

先进先出。异步操作比如fetch setTimeout setInterval 压入调用栈中时,消息会去到消息队列中,等到调用栈清空再执行

2. 题目

var p = new Promise(resolve => {
    console.log(4)
    resolve(5)
})
function fun1() {
    console.log(1)
}
function fun2(){
    setTimeout(() => {
        console.log(2)
    },0)
    fun1()
    console.log(3)
    p.then(resolve => {
        console.log(resolve)
    })
}
func2()

3. 过程

new Promise() // 进栈1
输出 4 
resolve(5) // 进微任务1
new Promise() // 出栈1
fun2() // 进栈2
setTimeout(() => {
        console.log(2)
    },0) // 进栈3
console.log(2) // 进任务队列1
setTimeout(() => {
        console.log(2)
    },0) // 出栈2
fun1() // 进栈4
输出 1
fun1() // 出栈3
输出 3
resolve(5) // 微任务1执行
输出 5
resolve(5) // 微任务1清空
输出 2 // 任务队列1执行
fun2() // 出栈4

4. 答案

4
1
3
5
2
posted @ 2022-03-11 14:00  沧浪浊兮  阅读(27)  评论(0)    收藏  举报