对于事件循环机制的补充

在之前的一篇文章中,小次简单的介绍了 Javascript 中的 Event Loop,没看过的小伙伴可以点击下方传送门:

Javascript 基础夯实——理解 Event Loop、Micro Task & Macro Task

上周有一位小伙伴来找小次对这个话题又进行了一番探讨,内容是关于在 Macro Task 执行时,如果有新的 Micro Task 入栈,那么这个新任务会在什么时间执行呢?

下面是一种可能存在的情况:

function macro () {
  setTimeout(() => {
      micro()
    })
}

function micro () {
    new Promise.resolve().then(() => {
      ...
    })
}

macro()

可能存在的情况

  1. 当前 Macro Task 栈中有多个任务时,新的 Micro Task 将会在所有 Marco Task 完成之后的下一次主任务及 UI 渲染之间执行
对于事件循环机制的补充_第1张图片
  1. 新的 Micro Task 会在当前正在执行的 Macro Task 结束之后执行,并且如果 Micro Task 中有更新 UI 的任务,剩余的 Macro Task 会在 UI 更新完成后执行
对于事件循环机制的补充_第2张图片

当然,情况可能并不只有上面两种。但是可以发现的是,上面两种情况中都没有提到 Main Task 的执行时机,因为只要 Main Task 存在,它就会在当前任务执行完毕后立即执行,优先级是最高的。

下面就验证一下上面两种情况的猜测是否正确。

验证代码

// html

// javascript const $test = document.getElementById('test') let counter = 0 function func1 () { $test.innerText = ++counter alert('func1') } function func2 () { $test.innerText = ++counter alert('func2') } function func3 () { $test.innerText = ++counter alert('func3') } function func4 () { $test.innerText = ++counter alert('func4') } (function () { // main task func1() // macro task setTimeout(() => { func2() // micro task Promise.resolve().then(func4) Promise.resolve().then(func3) }, 0) // macro task setTimeout(func1, 0) // micro task Promise.resolve().then(func3) // main task func4() })()

上面的代码中,在 setTimeout 执行时,向 Micro Task 中添加了两个任务,并且不管是执行 Main Task,Macro Task 还是 Micro Task 都会对 UI 进行更新,这也能够更方便我们理清楚 UI 更新的时机。

在代码中使用 alert,是为了能够更明显地看到 UI 更新的情况,因为 alert 会阻塞代码和 UI 的更新

下面直接看上面验证代码的执行情况:

1  - alert func1
2  - alert func4
3  - alert func3
4  - UI update -- counter = 3
5  - alert func2
6  - alert func4
7  - alert func3
8  - UI update -- counter = 6
9  - alert func1
10 - UI update -- counter = 7

总结一下上面验证代码得出的结论:

如果在 Macro 中有新的 Micro 入栈,Micro 的执行总是在 Macro 之前,并且会在 Micro 全部执行完毕后才会更新 UI 和执行下一个 Macro

扫码关注微信公众号【前端程序员的斜杠青年进化录】
微信扫码,给我赞赏一下~

你可能感兴趣的:(对于事件循环机制的补充)