Event Loop 事件循环

全文:https://juejin.cn/post/6844903968292749319

JS 运行机制

JS 的执行是单线程的,所谓的单线程就是事件任务要排队执行,前一个任务结束,才会执行后一个任务,这就是同步任务,为了避免前一个任务执行了很长时间还没结束,那下一个任务就不能执行的情况,引入了异步任务(js 的异步事件就是依赖于事件循环机制)的概念。

JS 运行机制步骤

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  2. 主线程之外,还存在一个任务队列(task queue)。只要异步任务有了运行结果,会把其回调函数作为一个任务添加到任务队列中。
  3. 一旦执行栈中的所有同步任务执行完毕,就会读取任务队列,看看里面有那些任务,将其添加到执行栈,开始执行。
  4. 主线程不断重复上面的第三步。也就是常说的事件循环(Event Loop)。

 

  • 主线程:也就是 js 引擎执行的线程,这个线程只有一个,页面渲染、函数处理都在这个主线程上执行。
  • 工作线程:也称幕后线程,这个线程可能存在于浏览器或js引擎内,与主线程是分开的,处理文件读取、网络请求等异步事件。

两个任务队列

宏任务(Macrotask)

  • setTimeout
  • setInterval
  • setImmediate(nodejs,在当前"任务队列"的尾部添加事件)
  • I/O
  • 用户交互操作,UI渲染

微任务(Microtask)

  • Promise(重点)
  • process.nextTick(nodejs,当前"执行栈"的尾部,下一次EventLoop(主线程读取"任务队列")之前)
  • Object.observe(不推荐使用)

process.nextTick和setImmediate的一个重要区别:

  • 多个process.nextTick语句总是在当前"执行栈"一次执行完,
  • 多个setImmediate可能则需要多次loop才能执行完。

由于process.nextTick指定的回调函数是在本次"事件循环"触发,而setImmediate指定的是在下次"事件循环"触发,所以很显然,前者总是比后者发生得早,而且执行效率也高(因为不用检查"任务队列")。

事件循环

  1. 检查宏任务队列是否为空,若不为空,则进行下一步,若为空,则跳到3
  2. 从宏任务队列中取队首(在队列时间最长)的任务进去执行栈中执行(仅仅一个),执行完后进入下一步
  3. 检查微任务队列是否为空,若不为空,则进入下一步,否则,跳到1(开始新的事件循环)
  4. 从微任务队列中取队首(在队列时间最长)的任务进去事件队列执行,执行完后,跳到3 其中,在执行代码过程中新增的microtask任务会在当前事件循环周期内执行,而新增的宏任务任务只能等到下一个事件循环才能执行了。

简而言之,一次事件循环只执行处于宏任务队首的任务,执行完成后,立即执行微任务队列中的所有任务。

第一次执行异步任务的时候会先清空微任务队列,然后才是本次事件循环中的宏任务,然后是下次事件循环的微任务被清空,再是宏任务,如此循环往复。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值