事件循环翻译参考
规范翻译
声明:本文原文由 WHATWG 编写,此文作为其2024年7月8日修改的一版中,事件循环部分的翻译,以提供相关讨论的对照。文中超链接以下划线标志,如果对本站进行跳转,特意以(本文链接)文字区分。翻译风格以原文使用的伪代码风格进行,存在一些类似于数学中的语法倒装,方便使用计算机思维进行理解,可能翻译质量一般,还请见谅。
原文项目许可证,Copyright © WHATWG (Apple, Google, Mozilla, Microsoft)
8.1.7 事件循环
8.1.7.3 处理模型
一个事件循环必须通过以下步骤持续运行,只要当其仍然存在:
- 声明 oldestTask 和 taskStartTime 为 null。
- 如果事件循环有至少有一个可运行任务的任务队列,那么:
- 声明 taskEndTime 为不安全的共享的当前时间。高精度时间
- 如果 oldestTask 非 null,则:
- 如果此事件循环是window 事件循环,且其所有事件循环的任务队列中没有可运行任务,则:
- 赋值此事件循环的上个空闲周期开始时间以不安全的共享的当前时间。
- 声明 computeDeadline 为以下步骤:
- 声明 deadline 为此事件循环的上个空闲周期开始时间再加 50。 注意:给定未来 50ms 的上限以确保在用户感知阈值内可以响应新的用户输入。
- 声明 hasPendingRenders 为 false。
- 对于此事件循环的所有相同循环窗口中的每个 windowInSameLoop:
- 如果 hasPendingRenders 为 true,则:
- 返回 deadline。
- 对于此事件循环同循环窗口 的每个窗口 win,为 win 执行开始空闲期算法,传递以下步骤(作为参数):调用 computeDeadline,对于其结果,给定 win 相关设定对象的跨源隔离能力以粗化,这之后返回该值。REQUESTIDLECALLBACK
- 如果此循环是worker 事件循环,则:
- 如果此事件循环代理的单一域(Realm)的全局对象是一个被支持的 DedicatedWorkerGlobalScope,且用户代理坚信代理自身将从执行其此次渲染更新中受益,则:
- 声明 now 为给定 DedicatedWorkerGlobalScope 的当前高精度时间。[高精度时间]
- 为 DedicatedWorkerGlobalScope 运行所有动画帧回调,传入 now 作为时间戳。
- 更新该 Dedicated Worker 的渲染以反映当前的状态。 注意:类似于在 window 事件循环中更新渲染的注意事项(见上),用户代理可以决定 Dedicated Worker 渲染的速率。
- 如果该事件循环的所有任务队列都没有任务,且 WorkerGlobalScope 对象的关闭标志为 true,则销毁事件循环,中止这些步骤,恢复后续 Web Worker 章节中描述的运行 worker 的步骤。
- 如果此事件循环代理的单一域(Realm)的全局对象是一个被支持的 DedicatedWorkerGlobalScope,且用户代理坚信代理自身将从执行其此次渲染更新中受益,则:
window 事件循环 eventLoop 也必须并行地运行下述步骤,只要当其仍然存在:
- 等待,直到至少有一个“可通行”(特殊数据结构,这里作名词) navigable,其活动文档相关代理的事件循环是 eventLoop,且其可能具有渲染机会(本文链接)。
- 赋值 eventLoop 的上次渲染机会时间为不安全的共享的当前时间。
- 对于每个具有渲染机会的 navigable,给定 navigable 的活动窗口以在渲染任务源上入队一个全局任务,从而更新渲染。
- 声明 frameTimestamp 为 eventLoop 的上次渲染机会时间。
- 声明 docs 为所有相关代理的事件循环是 eventLoop 的完全活动 Document 对象,其任意排序但需要满足以下条件:
- 过滤不可渲染的文档:从 docs 中移除满足下列任意条件的所有 Document doc:
- 非必要渲染:从 docs 中移除满足下列所有条件的所有 Document doc:
- 从 docs 中移除由于其他理由,用户代理坚信其适合跳过更新渲染的所有 Document doc。 注意: 此步骤标明了过滤不可渲染的文档阻止用户代理在无法向用户呈现新内容时更新渲染。 此步骤标明了非必要渲染阻止用户代理在没有新内容需要绘制时阻止更新渲染。 此步骤使用户代理能够因其他理由阻止下列步骤运行,例如,为确保某些任务在彼此之后能够立刻执行,仅交叉微任务检查点(本文链接)(且不交叉其他,如动画帧回调)。具体来说,用户代理可能希望合并计时器回调到一起,而不立刻渲染更新。
- 对于 docs 中的每个 doc,揭示 doc。
- 对于 docs 中的每个 doc,如果其节点“可通行”是一个顶级的“可遍历”(特殊的数据结构,原文中形作名),为其刷新自动聚焦候选。
- 对于 docs 中的每个 doc,运行调整尺寸步骤。[CSSOMVIEW]
- 对于 docs 中的每个 doc,运行滚动步骤。[CSSOMVIEW]
- 对于 docs 中的每个 doc,为 doc 求值媒体查询并报告改变。CSSOMVIEW
- 对于 docs 中的每个 doc,为 doc 更新动画并发送事件,给定 frameTimestamp 和 doc 相关全局对象作为时间戳,以[传入相对高精度时间](relative high resolution time)。[WEBANIMATIONS]
- 对于 docs 中的每个 doc,为 doc 运行全屏步骤。[FULLSCREEN]
- 对于 docs 中的每个 doc,如果用户代理检测到与任一 CanvasRenderingContext2D 或 OffscreenCanvasRenderingContext2D—— context ——相关联的后备存储已经丢失,则用户代理必须为每个类似的 context 运行上下文丢失步骤:
- 声明 canvas 为 context 的 canvas 属性,如果上下文是一个 CanvasRenderingContext2D,否则,声明其为 context 相关的 OffscreenCanvas 对象。
- 赋值 context 的上下文丢失为 true。
- 给定 context 以重置渲染上下文到其默认状态。
- 声明 shouldRestore 为于 canvas 上触发一个名为 contextlost 的事件的结果,该事件的 cancelable 属性被初始化为 true。
- 如果 shouldRestore 为 false,则中止这些步骤。
- 尝试通过使用 context 的属性创建后备存储并将它们与 context 相关联的方法,来恢复 context。如果此方法失败,则中止这些步骤。
- 赋值 context 的上下文丢失为 false。
- 于 canvas 上触发一个名为 contextrestored 的事件。
- 对于 docs 中的每个 doc,为 doc 运行动画帧回调,给定 frameTimestamp 和 doc 相关全局对象作为时间戳,以传入相对高精度时间。
- 声明 unsafeLayoutStartTime 为不安全的共享的当前时间。
- 对于 docs 中的每个 doc:
- 声明 resizeObserverDepth 为 0
- 满足 true 时:
- 为 doc 重新计算样式和更新布局
- 声明 hadInitialVisibleContentVisibilityDetermination 为 false。
- 对于每个“content-visibility”值为“auto”的元素 element:
- 如果 hadInitialVisibleContentVisibilityDetermination 为 true,则继续。 注意:此步骤的意图是为了进行初始视口邻近度确定,其会立即生效,然后在此循环中稍前的某一步骤里的,完成的样式和布局计算中反映出来。非初始的邻近度确定将在下一个渲染机会中生效。[CSSCONTAIN]
- 为 doc 按深度收集活动的调整尺寸观测 resizeObserverDepth。
- 如果 doc 有活动的调整尺寸观测:
- 赋值 resizeObserverDepth 以给定 doc 广播活动的调整尺寸观测的结果。
- 继续。
- 否则,中断
- 如果 doc 有跳过的调整尺寸观测,则给定 doc 传递调整尺寸循环错误
- 对于 docs 中的每个 doc,如果 doc 的聚焦区域不是一个可聚焦的区域,则运行为 doc 的视口 运行聚焦步骤,且赋值 doc 相关全局对象导航 API的导航进行期间焦点被改变为 false。 示例:比方说,这可能由于元素被添加了 hidden 属性,导致其停止被渲染而发生。也可能在 input 元素被禁用时,在该元素上发生。
- 对于 docs 中的每个 doc,为 doc 执行待定的过渡操作。[CSSVIEWTRANSITIONS]
- 对于 docs 中的每个 doc,为 doc 运行更新相交观测步骤,给定 now 和 doc 相关全局对象作为时间戳,以传入相对高精度时间。[INTERSECTIONOBSERVER]
- 对于 docs 中的每个 doc,给定不安全的样式和布局开始时间 unsafeStyleAndLayoutStartTime,从而为 doc 记录渲染时间。
- 对于 docs 中的每个 doc,为 doc 标记绘制时间。
- 对于 docs 中的每个 doc,更新 doc 及其节点对应“可通行”类型值的渲染和用户界面,以反映当前状态。
- 对于 docs 中的每个 doc,给定 doc 以处理顶端层移除。 “可通行”类型值具有一个渲染机会,如果用户代理当前能够将该值的内容呈现给用户。这考虑了硬件刷新率的限制和用户代理出于性能原因的节流,即使内容在视口之外,其内容也可以是可呈现的。 “可通行”类型值的渲染机会(本文链接)基于硬件限制和其他因素决定。硬件限制,如显示器的刷新率。其他因素,如页面性能,或是该“可通行”类型值的活动文档可见状态是否为“visible”。渲染机会通常会以恒定间隔发生。 注意:此规范并未强制要求任何特定的模型以选择渲染机会。但举例来说,如果浏览器尝试达到 60Hz 刷新率,则渲染机会最多每60分之一秒(约 16.7ms)出现一次。如果浏览器发现“可通行”类型值无法维持此速率,它可以为该“可通行”类型值降至更可维持的每秒30次渲染机会,而不是间接地掉帧。类似地,如果一个“可通行”类型值不可见,用户代理可以决定将对应页面降至更慢的每秒4个渲染机会,甚至更低。
当用户代理要执行微任务检查点时:
- 如果该事件循环的正在执行微任务检查点为 true,则返回:
- 赋值该事件循环的正在执行微任务检查点为 true。
- 满足该事件循环非空时:
- 对于可靠事件循环为该事件循环的每个环境设定对象,于其上通知将被拒绝的期约。
- 清理 Indexed Database 事务。
- 执行 ClearKeptObjects()。
- 赋值该事件循环的正在执行微任务检查点为 false。
- 为微任务检查点记录时间信息。
当一个并行地运行的算法要等待一个稳定状态时,用户代理必须入队一个微任务,然后停止执行(算法的执行将在微任务运行时恢复,正如下列步骤中所描述的那样),该微任务运行以下步骤:
- 运行算法的同步部分。
- 如果合适,并行地恢复算法的执行,如算法步骤中所述。
表明执行事件循环直到满足某一条件 gloal 的算法步骤等同于替换为以下代码步骤:
- 声明 task source 为任务的源。
- 声明 old stack 为JavaScript 执行上下文栈的副本。
- 清空 JavaScript 执行上下文栈。
- 执行微任务检查点(https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint)。
- 并行地:
- 等待,直到条件 goal 满足。
- 在任务源上入队一个任务以:
- 替换 JavaScript 执行上下文栈为 old stask。
- 执行原始算法中,该执行事件循环(本文链接)实例后出现的任何步骤。
- 停止 task,允许任何调用它的算法恢复。
部分翻译对照表
原文 | 翻译 | 备注 |
---|---|---|
let … be | 声明……为 | 声明……并赋值 |
set … to | 赋值……以 | |
if … then | 如果……则 | |
is … | 为… | |
is variable | 是 variable | 等效于浅比较上相等,是同一值 |
is not… | 非… | |
for B of A | 对于 B 中的每个 A | 对 A 进行迭代,每趟迭代的元素以 B 表示 |
while conditions | 满足某条件时 | 循环语句 |
do sth. given … | 给定……以(从而)做某事 | 给定参数执行算法 |
perform … | 执行…… | |
excute … | 执行…… | |
resume | 恢复 | |
continue | 继续 | 进行算法步骤中循环的下一趟迭代 |
break | 中断 | 跳出当前循环 |
otherwise | 否则 | |
current | 当前 | |
destroy | 销毁 | |
abort | 中止 | |
skipped | 跳过的 | |
detect | 检测到 | |
disabled | 禁用 | |
this/that/the | 此/该 | |
invoke | 调用 | 指调用系统外事物,中文可概括 |
call | 调用 | |
spin the event loop | 执行事件循环 | spin 原指高速旋转,计算机科学中指代循环或迭代的执行过程 |
environment settings object | 环境设置对象 | |
script evaluation | 脚本求值 | |
append | 添加 | |
set | 集合 | |
map | 映射 | |
list | 列表 | |
resize | 调整尺寸 | |
scroll | 滚动 | |
animation frame callback(s) | 动画帧回调 | |
timer callback(s) | 计时器回调 | |
pending | 待定 | |
suspend | 挂起 | |
block | 阻塞 | |
active | 活动 | 活动有活跃之意,由惯例使用前者 |
microtask checkpoint(s) | 微任务检查点 | |
map of animation frame callbacks | 动画帧回调映射 | |
active window | 活动窗口 | 活动 |
map of active timers | 活动计时器映射 | |
update the rendering | 更新渲染 | |
last render opportunity time | 上个渲染机会 | |
… document | ……文档 | 属于某数据结构的文档, 文中代指 Document 或 null |
Document (object) | Document (对象) | 均代指某一类特殊数据结构 |
navigable | “可通行”类型(的值) | navigable 形作名,类型就叫做“可通行” |
node navigable | 节点对应“可通行”类型值 | |
navigable container | “可通行”类型值的容器 | |
top-level traversable | 顶级的“可遍历” | 指一类数据结构,形容词作名词 |
shadow-including tree order | 影子包含树顺序 | |
render-blocked | 渲染阻塞的 | |
visibility state | 可见状态 | |
coarsen | 粗化 | |
view transition(s) | 视图转换 | |
the backing storage | 后备存储 | |
context | 上下文 | |
attribute | 属性 | |
restore | 恢复 | |
recalculate styles and update layout | 重新计算样式和更新布局 | 即重绘和重排,(re)paint 和 layout/(re)flow |
proximity to the viewport | 视口邻近度 | 原文此时元素可近或远,故译邻近度 |
fire an event | 触发(一个)事件 | |
determine | 确定 | |
be not determined | 待定 | |
is not determined | 待定 | |
be relevant to the user | 用户相关的 | |
resize observer | 调整尺寸观察者 | |
resize observation | 调整尺寸观测 | |
top layer | 顶端层 | 特殊名词,故据上下文作区分,顶(端) |
rate | 速率 | |
frame rate | 帧率 | |
drop frame | 丢帧 | |
rejected | 拒绝 | |
promise | 期约 | |
notify | 通知 | |
about rejected promise | 将被拒绝的期约 | 特殊名词,原文省略了介词以简写 |