事件循环翻译参考


规范翻译

声明:本文原文由 WHATWG 编写,此文作为其2024年7月8日修改的一版中,事件循环部分的翻译,以提供相关讨论的对照。文中超链接以下划线标志,如果对本站进行跳转,特意以(本文链接)文字区分。翻译风格以原文使用的伪代码风格进行,存在一些类似于数学中的语法倒装,方便使用计算机思维进行理解,可能翻译质量一般,还请见谅。

原文链接

原文项目许可证,Copyright © WHATWG (Apple, Google, Mozilla, Microsoft)

8.1.7 事件循环

8.1.7.3 处理模型

一个事件循环必须通过以下步骤持续运行,只要当其仍然存在:

  1. 声明 oldestTasktaskStartTime 为 null。
  2. 如果事件循环有至少有一个可运行任务任务队列,那么:
    1. 声明 taskQueue 为所述任务队列之一,以实现定义的风格进行选择。
    1. 赋值 taskStartTime不安全的共享的当前时间
    2. 赋值 oldestTasktaskQueue 中第一个可运行任务,同时从 taskQueue移除
    3. 如果 oldestTask文档非 null,则给定 taskStartTimeoldestTask文档记录任务开始时间
    4. 赋值事件循环当前运行任务oldestTask
    5. 执行 oldestTask步骤
    6. 赋值事件循环当前运行任务为 null,回到初始值。
    7. 执行一个微任务检查点本文链接)。
  3. 声明 taskEndTime不安全的共享的当前时间高精度时间
  4. 如果 oldestTask 非 null,则:
    1. 声明 top-level browsing contexts 为一个空集合
    2. 对于 oldestTask脚本求值的环境设定对象集合中的每个环境设定对象 settings
      1. 声明 globalsettings全局对象
      2. 如果 globalWindow 对象,则继续
      3. 如果 global浏览上下文为 null,则继续
      4. 声明 tlbcglobal浏览上下文顶级浏览上下文
      5. 如果 tlbc 非 null,则将其添加top-level browsing contexts
    3. 报告长任务,传入 taskStartTimetaskEndTimetop-level browsing contextsoldestTask
    4. 如果 oldestTask文档 非 null,则给定 taskEndTimeoldestTask记录任务结束时间
  5. 如果此事件循环window 事件循环,且其所有事件循环任务队列中没有可运行任务,则:
    1. 赋值此事件循环上个空闲周期开始时间不安全的共享的当前时间
    2. 声明 computeDeadline 为以下步骤:
      1. 声明 deadline 为此事件循环上个空闲周期开始时间再加 50。 注意:给定未来 50ms 的上限以确保在用户感知阈值内可以响应新的用户输入。
      2. 声明 hasPendingRenders 为 false。
      3. 对于此事件循环所有相同循环窗口中的每个 windowInSameLoop
        1. 如果 windowInSameLoop动画帧回调映射,或者,如果用户代理确信 windowInSameLoop 可能有阻塞的渲染更新,那么赋值 hasPendingRenders 为 true。
        2. 声明 timerCallbackEstimateswindowInSameLoop活动计时器映射进行获取全部值的结果。
        3. 对于 timerCallbackEstimates 中的每个 timeoutDeadline,如果 timeoutDeadline 小于 deadline,赋值 deadlinetimeoutDeadline
      4. 如果 hasPendingRenders 为 true,则:
        1. 声明 nextRenderDeadline 为此事件循环上个渲染机会时间加上(1000除以当前刷新率)。 刷新率可以是硬件上的或是特定于实现的。对于 60Hz 的刷新率,nextRenderDeadline 可能是上次渲染机会时间后约 16.67ms.
        2. 如果 nextRenderDeadline 小于 deadline,则返回 nextRenderDeadline
      5. 返回 deadline
    3. 对于此事件循环同循环窗口 的每个窗口 win,为 win 执行开始空闲期算法,传递以下步骤(作为参数):调用 computeDeadline,对于其结果,给定 win 相关设定对象跨源隔离能力粗化,这之后返回该值。REQUESTIDLECALLBACK
  6. 如果此循环是worker 事件循环,则:
    1. 如果此事件循环代理的单一域(Realm)全局对象是一个被支持的 DedicatedWorkerGlobalScope,且用户代理坚信代理自身将从执行其此次渲染更新中受益,则:
      1. 声明 now 为给定 DedicatedWorkerGlobalScope当前高精度时间。[高精度时间]
      2. DedicatedWorkerGlobalScope 运行所有动画帧回调,传入 now 作为时间戳。
      3. 更新该 Dedicated Worker 的渲染以反映当前的状态。 注意:类似于在 window 事件循环更新渲染的注意事项(见上),用户代理可以决定 Dedicated Worker 渲染的速率。
    2. 如果该事件循环的所有任务队列都没有任务,且 WorkerGlobalScope 对象的关闭标志为 true,则销毁事件循环,中止这些步骤,恢复后续 Web Worker 章节中描述的运行 worker 的步骤。

window 事件循环 eventLoop 也必须并行地运行下述步骤,只要当其仍然存在:

  1. 等待,直到至少有一个“可通行”(特殊数据结构,这里作名词) navigable,其活动文档相关代理事件循环eventLoop,且其可能具有渲染机会本文链接)。
  2. 赋值 eventLoop上次渲染机会时间不安全的共享的当前时间
  3. 对于每个具有渲染机会navigable,给定 navigable活动窗口以在渲染任务源入队一个全局任务,从而更新渲染
  1. 声明 frameTimestampeventLoop上次渲染机会时间
  2. 声明 docs 为所有相关代理的事件循环是 eventLoop完全活动 Document 对象,其任意排序但需要满足以下条件:
  3. 过滤不可渲染的文档:从 docs 中移除满足下列任意条件的所有 Document doc
  4. 非必要渲染:从 docs 中移除满足下列所有条件的所有 Document doc
  5. docs 中移除由于其他理由,用户代理坚信其适合跳过更新渲染的所有 Document doc。 注意: 此步骤标明了过滤不可渲染的文档阻止用户代理在无法向用户呈现新内容时更新渲染。 此步骤标明了非必要渲染阻止用户代理在没有新内容需要绘制时阻止更新渲染。 此步骤使用户代理能够因其他理由阻止下列步骤运行,例如,为确保某些任务在彼此之后能够立刻执行,仅交叉微任务检查点本文链接)(且不交叉其他,如动画帧回调)。具体来说,用户代理可能希望合并计时器回调到一起,而不立刻渲染更新。
  6. 对于 docs 中的每个 doc揭示 doc
  7. 对于 docs 中的每个 doc,如果其节点“可通行”是一个顶级的“可遍历”(特殊的数据结构,原文中形作名),为其刷新自动聚焦候选
  8. 对于 docs 中的每个 doc,运行调整尺寸步骤[CSSOMVIEW]
  9. 对于 docs 中的每个 doc,运行滚动步骤[CSSOMVIEW]
  10. 对于 docs 中的每个 doc,为 doc 求值媒体查询并报告改变CSSOMVIEW
  11. 对于 docs 中的每个 doc,为 doc 更新动画并发送事件,给定 frameTimestampdoc 相关全局对象作为时间戳,以[传入相对高精度时间](relative high resolution time)。[WEBANIMATIONS]
  12. 对于 docs 中的每个 doc,为 doc 运行全屏步骤[FULLSCREEN]
  13. 对于 docs 中的每个 doc,如果用户代理检测到与任一 CanvasRenderingContext2DOffscreenCanvasRenderingContext2D—— context ——相关联的后备存储已经丢失,则用户代理必须为每个类似的 context 运行上下文丢失步骤
    1. 声明 canvascontextcanvas 属性,如果上下文是一个 CanvasRenderingContext2D,否则,声明其为 context 相关的 OffscreenCanvas 对象
    2. 赋值 context上下文丢失为 true。
    3. 给定 context重置渲染上下文到其默认状态
    4. 声明 shouldRestore 为于 canvas触发一个名为 contextlost 的事件的结果,该事件的 cancelable 属性被初始化为 true。
    5. 如果 shouldRestore 为 false,则中止这些步骤。
    6. 尝试通过使用 context 的属性创建后备存储并将它们与 context 相关联的方法,来恢复 context。如果此方法失败,则中止这些步骤。
    7. 赋值 context上下文丢失为 false。
    8. canvas触发一个名为 contextrestored 的事件。
  14. 对于 docs 中的每个 doc,为 doc 运行动画帧回调,给定 frameTimestampdoc 相关全局对象作为时间戳,以传入相对高精度时间
  15. 声明 unsafeLayoutStartTime不安全的共享的当前时间
  16. 对于 docs 中的每个 doc
    1. 声明 resizeObserverDepth 为 0
    2. 满足 true 时:
      1. doc 重新计算样式和更新布局
      2. 声明 hadInitialVisibleContentVisibilityDetermination 为 false。
      3. 对于每个“content-visibility”值为“auto”的元素 element
        1. 声明 checkForInitialDetermination 为 true,如果 element视口邻近度待定,且其非用户相关的。否则,声明 checkForInitialDetermination 为 false。
        2. 确定 element视口邻近度
        3. 如果 checkForInitialDetermination 为 true,且 element 此时是用户相关的,则赋值 hadInitialVisibleContentVisibilityDetermination 为 true。
      4. 如果 hadInitialVisibleContentVisibilityDetermination 为 true,则继续。 注意:此步骤的意图是为了进行初始视口邻近度确定,其会立即生效,然后在此循环中稍前的某一步骤里的,完成的样式和布局计算中反映出来。非初始的邻近度确定将在下一个渲染机会中生效。[CSSCONTAIN]
      5. doc 按深度收集活动的调整尺寸观测 resizeObserverDepth
      6. 如果 doc 有活动的调整尺寸观测
        1. 赋值 resizeObserverDepth 以给定 doc 广播活动的调整尺寸观测的结果。
        2. 继续
      7. 否则,中断
    3. 如果 doc 有跳过的调整尺寸观测,则给定 doc 传递调整尺寸循环错误
  17. 对于 docs 中的每个 doc,如果 doc聚焦区域不是一个可聚焦的区域,则运行为 doc视口 运行聚焦步骤,且赋值 doc 相关全局对象导航 API导航进行期间焦点被改变为 false。 示例:比方说,这可能由于元素被添加了 hidden 属性,导致其停止被渲染而发生。也可能在 input 元素被禁用时,在该元素上发生。
  1. 对于 docs 中的每个 doc,为 doc 执行待定的过渡操作[CSSVIEWTRANSITIONS]
  2. 对于 docs 中的每个 doc,为 doc 运行更新相交观测步骤,给定 nowdoc 相关全局对象作为时间戳,以传入相对高精度时间[INTERSECTIONOBSERVER]
  3. 对于 docs 中的每个 doc,给定不安全的样式和布局开始时间 unsafeStyleAndLayoutStartTime,从而为 doc 记录渲染时间
  4. 对于 docs 中的每个 doc,为 doc 标记绘制时间
  5. 对于 docs 中的每个 doc,更新 doc 及其节点对应“可通行”类型值的渲染和用户界面,以反映当前状态。
  6. 对于 docs 中的每个 doc,给定 doc处理顶端层移除“可通行”类型值具有一个渲染机会,如果用户代理当前能够将该值的内容呈现给用户。这考虑了硬件刷新率的限制和用户代理出于性能原因的节流,即使内容在视口之外,其内容也可以是可呈现的。 “可通行”类型值渲染机会本文链接)基于硬件限制和其他因素决定。硬件限制,如显示器的刷新率。其他因素,如页面性能,或是该“可通行”类型值活动文档可见状态是否为“visible”。渲染机会通常会以恒定间隔发生。 注意:此规范并未强制要求任何特定的模型以选择渲染机会。但举例来说,如果浏览器尝试达到 60Hz 刷新率,则渲染机会最多每60分之一秒(约 16.7ms)出现一次。如果浏览器发现“可通行”类型值无法维持此速率,它可以为该“可通行”类型值降至更可维持的每秒30次渲染机会,而不是间接地掉帧。类似地,如果一个“可通行”类型值不可见,用户代理可以决定将对应页面降至更慢的每秒4个渲染机会,甚至更低。

当用户代理要执行微任务检查点时:

  1. 如果该事件循环正在执行微任务检查点为 true,则返回:
  2. 赋值该事件循环正在执行微任务检查点为 true。
  3. 满足该事件循环时:
    1. 声明 oldestMicrotask 为从事件循环微任务队列出队的结果。
    2. 赋值该事件循环当前运行任务 oldestMicrotask
    3. 运行 oldestMicrotask
    1. 赋值该事件循环当前运行任务以 null,回到初始值
  4. 对于可靠事件循环为该事件循环的每个环境设定对象,于其上通知将被拒绝的期约
  5. 清理 Indexed Database 事务
  6. 执行 ClearKeptObjects()。
  1. 赋值该事件循环正在执行微任务检查点为 false。
  2. 为微任务检查点记录时间信息

当一个并行地运行的算法要等待一个稳定状态时,用户代理必须入队一个微任务,然后停止执行(算法的执行将在微任务运行时恢复,正如下列步骤中所描述的那样),该微任务运行以下步骤:

  1. 运行算法的同步部分
  2. 如果合适,并行地恢复算法的执行,如算法步骤中所述。

表明执行事件循环直到满足某一条件 gloal 的算法步骤等同于替换为以下代码步骤:

  1. 声明 task 为该事件循环当前运行任务
  1. 声明 task source 为任务的
  2. 声明 old stackJavaScript 执行上下文栈的副本。
  3. 清空 JavaScript 执行上下文栈
  4. 执行微任务检查点(https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint)。
  1. 并行地
    1. 等待,直到条件 goal 满足。
    2. 在任务源上入队一个任务以:
      1. 替换 JavaScript 执行上下文栈old stask
      2. 执行原始算法中,该执行事件循环本文链接)实例后出现的任何步骤。
  2. 停止 task,允许任何调用它的算法恢复。

部分翻译对照表

部分翻译对照表
原文翻译备注
let … be声明……为声明……并赋值
set … to赋值……以
if … then如果……则
is …为…
is variablevariable等效于浅比较上相等,是同一值
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将被拒绝的期约特殊名词,原文省略了介词以简写