# 事件循环 Event Loop
Js 是单线程的一次只能做一件事情,让所有的事情变的有序就非常重要,所以用队列的数据结构保证任务的有序进行。因为有一些任务是非常耗时的,所以区分是异步的任务还是同步的任务。异步任务还会分为宏任务和微任务,当主线程执行完成之后,先查看微任务队列是否有任务,全部执行,再去执行下一个宏任务队列的一个任务,执行完成以后再去检查微任务队列,依次循环。
1.JS是单线程,防止代码阻塞,我们把代码(任务):同步和异步
2.同步代码给js引擎执行,异步代码交给宿主环境
3.同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
4.执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程是事件循环(eventloop)
# 名词解释
- 同步任务(synchronous)
- 异步任务(asynchronous)
- 宏任务(macro-task)
- 微任务(micro-task)
# 基本概念
浏览器
一个线程中,事件循环是唯一的,但是任务队列可以拥有俩个,一个任务队列 macro-task(宏任务)一个 micro-task(微任务),在最新标准中,它们被分别称为 task 与 jobs
node
node11.x 前后版本差异:之前按照宏任务优先级 一个宏任务队列搭配一个微任务队列,之后和浏览器一致
node 端的事件循环比浏览器更复杂,它的宏任务分为六个优先级,微任务分为两个优先级。node 端的执行规律是一个宏任务队列搭配一个微任务队列,而浏览器是一个单独的宏任务搭配一个微任务队列。但是在 node11 之后,node 和浏览器的规律趋同。
宏任务
- script
- setTimeout
- setInterval
- setImmediate(node)
- requestAnimationFrame(浏览器)
- UI render (浏览器)
- I/O
微任务
- Promise
- Object.observe
- MutationObserver(html5 新特性)
- process.nextTick(node) 优先级最高
# async/await 执行顺序
存在 await 后面如果是 常量 直接执行后面的语句
如果是一个 promise 需等到 promise 执行完成之后才执行后面语句
旧版 await 后面的流程在最后微任务结束执行
新版变的更快了 如果 await 后面直接跟的为一个变量 种情况的话相当于直接把 await 后面的代码注册为一个微任务 如果 await 后面跟的是一个异步函数的调用 会跳出 当前执行的异步函数,当所有微任务执行完毕以后,在回到这个函数执行后面的微任务
# node 和 浏览器 eventLoop 的主要区别
两者最主要的区别在于浏览器中的微任务是在每个相应的宏任务中执行的,而 nodejs 中的微任务是在不同阶段之间执行的
详情看事件循环顺序的网址:https://www.jsv9000.app/ (opens new window)
参考文章:
- 阿里一面:熟悉事件循环?那谈谈为什么会分为宏任务和微任务 (opens new window)
- 一次弄懂 Event Loop (opens new window)
- 📺 事件循环原理讲解 (opens new window)
- 📺 2014 年 JS 开发者大会上 philip_roberts 的演讲——What the heck is this event loop anyway? (opens new window)
- js 运行机制同步与异步(宏任务与微任务) (opens new window)
- 面试题:说说事件循环机制(满分答案来了 (opens new window)
- 这一次,彻底弄懂 JavaScript 执行机制 (opens new window)
- 📺事件循环-EventLoop (opens new window)