event loop js事件循环 microtask macrotask
来源:互联网 发布:打开文件的软件 编辑:程序博客网 时间:2024/06/04 19:15
放个面试题,抛个砖:
console.log('start')const interval = setInterval(() => { console.log('setInterval')}, 0)setTimeout(() => { console.log('setTimeout 1') Promise.resolve() .then(() => { console.log('promise 3') }) .then(() => { console.log('promise 4') }) .then(() => { setTimeout(() => { console.log('setTimeout 2') Promise.resolve() .then(() => { console.log('promise 5') }) .then(() => { console.log('promise 6') }) .then(() => { clearInterval(interval) }) }, 0) })}, 0)Promise.resolve() .then(() => { console.log('promise 1') }) .then(() => { console.log('promise 2') })
不着急揭晓答案,先分析
首先知晓:
js是单线程语言
也就是说一次就只能做一件事情。
多数的网站不需要大量计算,程序花费的时间主要集中在磁盘 I/O 和网络 I/O 上面
虽然SSD读取很快,但和CPU处理指令的速度比起来也不在一个数量级上,而且网络上一个数据包来回的时间更慢(注意过游戏的延迟吗)
so: 一些cpu直接执行的任务就成了优先执行主线任务,然后需要io返回数据的任务就成了等待被执行的任务
所以才会有同步任务(synchronous)和异步任务(asynchronous)之分
同步任务:
在主线程上排队执行的任务,前一个任务执行完毕,才能执行后一个任务;
异步任务:
不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
总之:
只要主线程空了,就会去读取”任务队列”,这就是JavaScript的运行机制
Microtasks Macrotasks
任务队列不止一个,还有 microtasks 和 macrotasks
microtasks:
- process.nextTick
- promise
- Object.observe
- MutationObserver
macrotasks:
- setTimeout
- setInterval
- setImmediate
- I/O
- UI渲染
whatwg规范:https://html.spec.whatwg.org/multipage/webappapis.html#task-queue
- 一个事件循环(event loop)会有一个或多个任务队列(task queue)
- task queue 就是 macrotask queue
- 每一个 event loop 都有一个 microtask queue
- task queue == macrotask queue != microtask queue
- 一个任务 task 可以放入 macrotask queue 也可以放入 microtask queue 中
理解了这些定义之后,再看执行原理:
事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。
还要注意一点:
包裹在一个 script 标签中的js代码也是一个 task 确切说是 macrotask。
所以文首面试题的答案为:
start
promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setTimeout 2
promise 5
promise 6
简单来讲,整体的js代码这个macrotask先执行,同步代码执行完后有microtask执行microtask,没有microtask执行下一个macrotask,如此往复循环至结束
- event loop js事件循环 microtask macrotask
- Node.js Event-loop事件循环
- event loop 事件循环
- js运行机制—事件循环(Event Loop)详解
- Node.js事件循环(Event Loop)和线程池详解
- glib之mainloop——event loop 事件循环
- JavaScript:彻底理解同步、异步和事件循环(Event Loop)
- Javascript运行机制中的事件循环(Event Loop)
- JavaScript的运行机制Event Loop(事件循环)
- JavaScript:彻底理解同步、异步和事件循环(Event Loop)
- JavaScript运行机制之事件循环(Event Loop)详解
- 彻底搞懂nodejs事件循环 Event Loop
- Js Event Loop
- 事件轮询(Event Loop)
- node.js的event loop
- libuv之事件循环loop
- javascript事件轮询(event loop)详解
- 理解Python事件驱动编程(Event Loop)
- JAVA可变形参方法
- Spring [boot] 使用技巧集合-不断积累
- 直方图处理(规定化)
- C#综合揭秘——细说事务
- CW3005|USB智能识别方案|赛微一级代理|中文规格书
- event loop js事件循环 microtask macrotask
- HDU 6033(Add More Zero) 简单数学题 Java
- 2017杭电多校联赛 1001 Add More Zero(取对数)HDU 6033
- 47. Permutations II
- Hadoop和Spark学习日记1
- 大型网站架构之分布式消息队列
- Linux配置好公钥后无法登陆
- make menuconfig异常
- UGUI 图集打包工具Sprite Packer