We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
为了协调事件、用户交互、脚本、呈现、网络等,UA必须使用事件循环的机制。事件循环有两种模式:用于browsing contexts(浏览环境上下文)的循环,以及用于workers的循环。
browsing contexts event loop
worker processing model
一个事件循环会有一个或者多个任务队列。任务队列是一个有序的list集合,用来处理下面的任务:
microtask
一个事件循环其实就是在不断运行下面这些步骤的操作: 1. 把oldestTask标记为oldest task. UA可以选择任意任务队列,如果没有选择跳到Microtasks微任务处理 2. 将当前运行任务设置成 oldestTask. 3. 运行 oldestTask. 4. 将事件循环的当前运行任务 置为null 5. 从任务队列中移除oldestTask. 6. Microtasks: 微任务检测点,执行微任务检测. 7. 更新渲染(Update rendering) 主要是浏览器渲染过程不详细展开. 8. worker事件循环判断.
null
true
false
上述概念为whatwg规范概念,具体实现还得看浏览器厂商。之所以称为事件循环,是因为它经常被用于类似如下的方式来实现:
whatwg
while (queue.waitForMessage()) { queue.processNextMessage(); }
由于js的运行环境是单线程的,函数调用会形成了一个栈帧,对象被分配在一个堆中,即用以表示一个大部分非结构化的内存区域 ,除此之外JavaScript 运行时还包含了一个待处理的消息队列。每一个消息都与一个函数相关联。当栈拥有足够内存时,从队列中取出一个消息进行处理。 看图来分析如下: 主线程运行时函数会被压入函数调用栈等待执行,当调用栈中的函数被调用时,任务分发器会根据任务源把对应任务放入不同的event队列中。如webaips产生的回调会被放入回调队列,微任务microtask会被放入微任务队列。事件循环处理器也就是event loop按照前面的步骤做loop。
event loop
当Node.js启动时会初始化event loop,下图是一个简化版的事件循环执行顺序,大体分为六个阶段。
┌───────────────────────┐ ┌─>│ timers │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ I/O callbacks │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ idle, prepare │ │ └──────────┬────────────┘ ┌───────────────┐ │ ┌──────────┴────────────┐ │ incoming: │ │ │ poll │<─────┤ connections, │ │ └──────────┬────────────┘ │ data, etc. │ │ ┌──────────┴────────────┐ └───────────────┘ │ │ check │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ └──┤ close callbacks │ └───────────────────────┘
setTimeout
setInterval
setImmediate
node
socket.on('close', ...)
对于定时器和浏览器API类似,需要注意的是定时器何时执行是由poll 阶段决定的,所有精确度不够有时可能被延迟。
poll
poll阶段主要做两件事:
如果event loop进入了 poll阶段,且代码未设定timer,将会发生下面情况:
一旦poll队列为空,事件循环将检查timer是否达到时间,如果有一个或者多个timer到达时间事件循环就会返回到timers阶段执行timers的回调.
这个阶段容许立即执行一个回调在poll阶段完成后,如果poll阶段处于空闲状态并且setImmediate的回调已经入队。那么事件循环将进入check阶段而不是等待.
check
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ https://html.spec.whatwg.org/multipage/webappapis.html#task-queue https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context https://www.jianshu.com/p/de7aba994523 https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ https://cnodejs.org/topic/57d68794cb6f605d360105bf
The text was updated successfully, but these errors were encountered:
No branches or pull requests
浏览器环境
基本概念
为了协调事件、用户交互、脚本、呈现、网络等,UA必须使用事件循环的机制。事件循环有两种模式:用于browsing contexts(浏览环境上下文)的循环,以及用于workers的循环。
每个
browsing contexts event loop
个至少含有一个browsing context上下文环境,该事件循环依赖与环境,环境消失的话该事件机制也将销亡.workers与此类似 每个worker 有一个事件循环,并通过
worker processing model
管理事件循环的生命周期.task queue(任务队列)
一个事件循环会有一个或者多个任务队列。任务队列是一个有序的list集合,用来处理下面的任务:
task(任务)
microtask
的flag用来检测微任务默认情况为false。来用防止注入事件时调用microtask
检测算法。Processing model(事件循环处理器)
一个事件循环其实就是在不断运行下面这些步骤的操作:
1. 把oldestTask标记为oldest task. UA可以选择任意任务队列,如果没有选择跳到Microtasks微任务处理
2. 将当前运行任务设置成 oldestTask.
3. 运行 oldestTask.
4. 将事件循环的当前运行任务 置为
null
5. 从任务队列中移除oldestTask.
6. Microtasks: 微任务检测点,执行微任务检测.
7. 更新渲染(Update rendering) 主要是浏览器渲染过程不详细展开.
8. worker事件循环判断.
微任务检测
true
null
false
事件循环
上述概念为
whatwg
规范概念,具体实现还得看浏览器厂商。之所以称为事件循环,是因为它经常被用于类似如下的方式来实现:由于js的运行环境是单线程的,函数调用会形成了一个栈帧,对象被分配在一个堆中,即用以表示一个大部分非结构化的内存区域 ,除此之外JavaScript 运行时还包含了一个待处理的消息队列。每一个消息都与一个函数相关联。当栈拥有足够内存时,从队列中取出一个消息进行处理。
看图来分析如下:
主线程运行时函数会被压入函数调用栈等待执行,当调用栈中的函数被调用时,任务分发器会根据任务源把对应任务放入不同的event队列中。如webaips产生的回调会被放入回调队列,微任务
microtask
会被放入微任务队列。事件循环处理器也就是event loop
按照前面的步骤做loop。注意
Node.js 环境
概念
当Node.js启动时会初始化event loop,下图是一个简化版的事件循环执行顺序,大体分为六个阶段。
setTimeout
和setInterval
的回调.setImmediate
所产生的回调外的所有回调.node
有时会阻塞这里.setImmediate
的回调.socket.on('close', ...)
.详细
timer 定时器
对于定时器和浏览器API类似,需要注意的是定时器何时执行是由
poll
阶段决定的,所有精确度不够有时可能被延迟。poll
poll
阶段主要做两件事:poll
队列中的事件.如果event loop进入了 poll阶段,且代码未设定timer,将会发生下面情况:
poll
队列为空,将会发生下面情况:setImmediate
设定了callback, event loop将结束poll阶段进入check阶段,并执行check阶段的事件.setImmediate
,event loop将阻塞在该阶段等待callbacks加入poll队列.一旦poll队列为空,事件循环将检查timer是否达到时间,如果有一个或者多个timer到达时间事件循环就会返回到timers阶段执行timers的回调.
check
这个阶段容许立即执行一个回调在poll阶段完成后,如果poll阶段处于空闲状态并且
setImmediate
的回调已经入队。那么事件循环将进入check
阶段而不是等待.参考
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop
https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://html.spec.whatwg.org/multipage/webappapis.html#task-queue
https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context
https://www.jianshu.com/p/de7aba994523
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
https://cnodejs.org/topic/57d68794cb6f605d360105bf
The text was updated successfully, but these errors were encountered: