事件循环机制(Event Loop)

什么是事件循环

是单线程的js在处理异步事件时进行的一种循环过程.也就是说发生异步事件的时候,这些事件会被加入到事件队列中挂起,等待主线程空闲的时候去执行.一旦主线程空闲,就会从事件队列中取出事件进行处理.处理完一个,再取出下一个事件进行处理,如此反复循环

事件循环解决了什么

让js可以在单线程中处理异步操作,避免了阻塞,这种机制在处理大量异步事件时,能够保持程序的稳定性

事件循环 -> 任务队列

过去把消息队列简单分为宏任务微任务,但是随着浏览器复杂度急剧提升,W3C已经不再使用宏任务的说法

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就一直等着。

在 JavaScript中任务分为同步与异步任务,其中异步任务又分为两种:宏任务(Macro Task)和 微任务(Micro Task)。同步任务(synchronous),异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

常见宏任务

  1. script标签中的代码
  2. setTimeout
  3. setInterval
  4. setImmediate(Node.js)
  5. IO
  6. UI 渲染
  7. MessageChannel

常见微任务

  1. Promise.then(非 new Promise)
  2. async
  3. await
  4. Object.observe
  5. MutationObserver

宏任务和微任务的执行顺序:总方针是先同步再异步,异步中先微任务,在宏任务

process.nextTick(Node.js)

在 Node.js 环境中,process.nextTick 的回调函数会在微任务队列中的其他任务之前执行,因此在输出顺序上会比 Promise.then 更早。而在浏览器环境中,nextTick 的回调函数会在当前微任务队列中的其他任务执行完毕后立即执行,因此在输出顺序上会比 Promise.then 更晚。

W3C最新的事件循环

参考W3C地址查看

每个任务都有一个任务类型,同一个类型的任务必须在一个队列里,不同类型的任务分属于不同的队列,在一次事件循环中,浏览器可以根据实际情况从不同队列中取出任务执行。 大概有以下几个的队列DOM操作用户交互网络请求网页导航和历史记录遍历渲染

同时浏览器必须准备好一个微队列,微队列中的任务优先于所有其他任务执行

目前的Chrome实现中,至少包含了以下队列:
队列类型描述优先级
微队列用于存放需要最快执行的任务最高
交互队列用于存放用户操作后产生的事件处理任务
延时队列用于存放计时器到达后的回调任务
网络队列用于处理网络活动产生的任务

在W3C中对于事件循环(Event Loop)的处理已经不再是之前的宏任务与微任务的方式了,每个任务都有一个任务类型,同一个类型的任务必须在一个队列里,不同类型的任务分属于不同的队列,在一次事件循环中,浏览器可以根据实际情况从不同队列中取出任务执行。但是浏览器也必须准备好一个微队列(microtask),微队列中的任务优先于所有其他任务执行。

事件循环导致的setTimeout有误差

在js中,setTimeout不是在指定的延迟时间后立即执行回调,而是将回调放入事件循环的队列中,等待主线程空闲的时候执行,但是实际执行的事件可能会收到任务队列中其他任务的影响,导致延迟,就比如指定的延迟时间到了,但是主线程还有一个网络请求等等,那么setTimeout就会被放到任务队列中等待主线程空闲在执行了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值