说说你对事件循环event loop的理解?

什么是事件循环机制?

事件循环分为两种,分别是浏览器事件循环node.js事件循环,本文主要对浏览器事件循环进行描述。
我们都知道JavaScript是一门单线程语言,指主线程只有一个。Event Loop事件循环,其实就是JS引擎管理事件执行的一个流程,具体由运行环境确定。目前JS的主要运行环境有两个,浏览器Node.js

先了解浏览器的进程和线程:

浏览器是多进程的,浏览器每一个打开一个Tab页面(网页)都代表着创建一个独立的进程(至少需要四个,若页面有插件运行,则五个)。渲染进程(浏览器内核)是多线程的,也是浏览器的重点,因为页面的渲染,JS执行等都在这个进程内进行
在这里插入图片描述

  1. GUI渲染线程

    负责渲染浏览器界面,包括解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
    当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。
    注意 : GUI渲染线程与JS引擎线程是互斥的。

  2. JS引擎线程

    也称为JS内核,负责解析处理Javascript脚本,运行代码。(例如V8引擎)。
    JS引擎一直等待并处理任务队列中任务。一个Tab页中无论什么时候都只有一个JS线程在运行JS程序

  3. 定时触发器线程

    setIntervalsetTimeout所在线程。通过此线程计时完毕后,添加到事件队列中,等待JS引擎空闲后执行

  4. 事件触发线程

    当一个事件被触发时该线程会把事件添加到事件队列,等待JS引擎的处理
    这些事件可来自JS引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

  5. 异步http请求线程

    XMLHttpRequest连接后是通过浏览器新开一个线程请求。
    将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JS引擎执行

Event Loop ( 事件循环 )

浏览器的事件循环分为同步任务异步任务;所有同步任务都在主线程上执行,形成一个函数调用栈(执行栈),而异步则先放到任务队列task queue)里,任务队列又分为宏任务macro-task)与微任务micro-task)。下面的整个执行过程就是事件循环

  • 宏任务大概包括::script(整块代码)、setTimeoutsetInterval、I/O、UI交互事件、setImmediatenode环境)

  • 微任务大概包括::new promise().then(回调)、MutationObserver(html5新特新)、Object.observe(已废弃)、process.nextTick(node环境)
    若同时存在promisenextTick,则先执行nextTick

宏任务与微任务

JavaScript代码运行时,任务分为宏任务微任务两种,Event Loop也将任务队列分为宏队列微队列分别管理宏任务和微任务,宏队列和微队列也具备队列特性:先进先出

事件循环的进程模型
  • 选择当前要执行的宏任务队列,选择一个最先进任务队列的宏任务,如果没有宏任务,则会跳转至微任务的执行步骤。
  • 将事件循环的当前运行宏任务设置为已选择的宏任务。
  • 运行宏任务。
  • 将事件循环的当前运行任务设置为null。
  • 将运行完的宏任务从宏任务队列中移除。
  • 微任务步骤:进入微任务检查点。
  • 更新界面渲染。
  • 返回第一步。
    只要主线程空了,就会读取任务队列,这就是js的运行机制,也被称为EventLoop机制。

在同一个上下文中,总的执行顺序:同步代码→微任务→宏任务

console.log("1")
setTimeout(()=>{
    console.log('2')
    new Promise(function(resolve){
     console.log("3")
      resolve();
}).then(function() {
        console.log('4')
    })
}, 0)

setTimeout(()=>{
    console.log('5')
    Promise.resolve().then(function() {
        console.log('6')
    })
}, 0)
console.log("7")

首先执行同步任务,先打印1
执行到第一个setTimeout属于宏任务,挂起放到宏任务队列,遇到第二个setTimeout也是挂起放到宏任务队列。
接着打印7。
同步任务执行完成→js执行栈为空→去查找微任务:微任务为空→查到宏任务。
执行第一个宏任务,打印2,接着执行new Promise,打印3,Promise.then属于微任务,挂起放到微任务队列中。
宏任务执行完成→js执行栈为空→查找微任务:打印4
继续循环查找宏任务,执行到第二个setTimeout,执行顺序同上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值