Javascript 事件循环机制

先看看大佬的文章👀

这个前端面试在搞事

80% 应聘者都不及格的 JS 面试题

涉及概念

  • 执行上下文(Execution context)
  • 函数调用栈(call stack)
  • 任务队列(task queue)
  • Promise

Javascript代码执行过程中,执行顺序依靠 函数调用栈、**任务队列 **来维护的

JavaScript的一大特点就是单线程,而这个线程中拥有唯一的一个事件循环

  • 一个线程中,事件循环时唯一的,但是任务队列可以有多个
  • 任务队列分为:macro-task(宏任务)、micro-task(微任务)
  • macro-task:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
  • micro-task: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)
  • setTimeout/Promise 等我们称之为任务源/任务分发器。而进入任务队列的是他们指定的具体执行任务。
  • 来自不同任务源的任务会进入到不同的任务队列。其中**setTimeoutsetInterval**是同源的
  • 事件循环的顺序,决定了JavaScript代码的执行顺序。
    • 执行macro-task 中的 script(整体代码),开始第一次循环,上下文进入函数调用栈,执行可执行代码,将遇到的任务入对应的队列,直到调用栈清空
    • 执行micro-task中的任务,通过调用栈执行,遇到任务入对应的队列,清空由执行宏任务产生的微任务,一次循环完成
    • 执行macro-task中的任务,开始第二次循环,通过调用栈执行,遇到任务入对应的队列
    • micro -> macro -> micro -> macro ....
  • 其中每一个任务的执行,无论是macro-task还是micro-task,都是借助函数调用栈来完成

注意结束的时间点⏱️

事件循环总结:

  • 先执行宏任务,在执行宏任务的过程中会产生微任务以及宏任务,在结束当前次宏任务后,去执行清空产生的微任务,当然宏任务执行的过程中也会产生宏任务,排在后续队列中
  • 执行上次循环产生的宏任务,开启下一次循环
  • 先前对于有所误解,不好意思😁
  • 事件循环,主要涉及三个模块:函数调用栈、任务队列、异步模块
  • 每次从宏任务队列开始,拿出一个宏任务进入函数调用栈,进行执行。
  • 函数调用栈执行完毕,去清空此次产生的微任务队列中的任务。
  • 再回到宏任务队列取一个任务去函数调用栈中执行,依此反复。
  • 注意,例如再函数调用栈中执行的过程中,产生的异步任务,如 setTimeout,是先进入 异步模块 (WebAPI),然后在合适的时机在进入到响应的宏任务队列。

栗子🌰

setTimeout(function() {
    console.log(1);
})

new Promise(function(resolve) {
    console.log(2);
    for(var i = 0; i < 1000; i++) {
        i == 99 && resolve();
    }
    console.log(3);
}).then(function() {
    console.log(4);
})

console.log(5);

最终输出结果:2 3 5 4 1

  • 首先,macro-task中只有script,循环开始

    r6FCQ.png

  • 执行可执行上下文,以及将其他宏任务、微任务入队列

    • setTimeout() -> macro-task
    • new promise().then -> micro-task 构造函数部分是在new的时候执行,不进入队列,直接入函数调用栈执行,所以此时依次输出 2、3

    r6ju4.png

  • 继续执行到最后console.log(5),此时输出 5

  • 至此宏任务第一个队列执行完毕,去清空,此次产生的微任务队列,及promise().then,此时输出 4

    r6bLd.png

  • 清空完毕,继续回到宏任务队列,再次循环,及执行setTimeout,此时输出 1

    r6V13.png

  • 至此清空,结束循环

    r6vDB.png


over~🎉

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值