我认为 Javascript 事件循环旨在跨 Web 浏览器以类似的方式执行 Macrotask 队列中的任务。简而言之(不考虑评估脚本、微任务队列等):
从 Macrotask 队列中取出最旧的任务并运行它
渲染
重复
我在 Chrome 中面临不一致,而 Firefox 在遵循上述步骤时似乎更加一致。
这里是 >silly< code example 来证明这个问题:
index.html
...
<head>
<script src="index.js" defer></script>
</head>
...
index.js
"use strict";
function sleep(ms)
{
const start = performance.now();
while ((performance.now() - start) < ms);
}
function doNextPart()
{
currentPart++;
sleep(20);
addToRender(currentPart.toString());
}
function addToRender(part)
{
partsList.push(part);
}
function render(timestamp)
{
frame++;
console.log(`frame: ${frame} \t rendering time: ${timestamp}`);
for (const part of partsList)
{
const itemDiv = document.createElement("div");
itemDiv.innerHTML = `part: ${part} || frame: ${frame}, ${timestamp}`;
partsContainerDiv.appendChild(itemDiv);
}
document.body.appendChild(partsContainerDiv);
partsList.length = 0;
if (frame <= 5)
{
window.requestAnimationFrame(render);
}
}
const partsContainerDiv = document.createElement("div");
const partsList = [];
let frame = 0;
let currentPart = 0;
window.requestAnimationFrame(render);
setTimeout(doNextPart);
setTimeout(doNextPart);
setTimeout(doNextPart);
这里有一些解释:
requestAnimationFrame()
用于渲染:partsList
数组中当前有什么然后清除该数组,当前frame
数,timestamp
doNexPart()
函数:只是使用sleep()
函数在给定时间内阻塞事件循环,然后将“结果”(
currentPart
)添加到partsList
数组进行渲染宏任务队列中添加了
doNextPart()
函数三次console.log()
用于记录所有 (5) 帧 - 主要用于最后一帧时间戳,没有来自 Macrotask 队列的任务 )这就是我期待的:
从 Macrotask 队列中获取任务 => 首先运行
doNextPart()
,它将“1”作为“结果”添加到 partsList
数组
render => 事件循环现在可以调用
render()
函数进行渲染,所以 HTML 输出是
part: 1 || frame: 1
重复
我希望最终的 HTML 输出应该是这样的:
part: 1 || frame: 1
part: 2 || frame: 2
part: 3 || frame: 3
以上是我在Firefox几乎一直得到的。
前三帧每帧花费大约25ms
sleep(20ms)
,另外两帧花费大约8ms(总共5帧)。
换句话说 - 它在任务之间呈现,因为它试图以通常由显示刷新率给出的比率呈现(假设每个 8ms 对于 120Hz) - 换句话说 Firefox 试图遵循步骤。
但是在Chrome的HTML输出是:
part: 1 || frame: 2
part: 2 || frame: 2
part: 3 || frame: 2
所以它在 一帧 中同时渲染,那一帧花了 91.7 毫秒。
当我查看“性能”选项卡时,任务按应有的方式执行,但绘制仅在最后一个之后完成。
但是当传递给
sleep()
函数的时间足够高(100ms对我有用)Chrome按预期呈现。
------------------------------------------------ ---------------------------------------------- ------
Chrome 版本测试:110.0.5481.178
Firefox 测试版本:110.0.1
主要来源:
------------------------------------------------ ---------------------------------------------- ------
我追求的是:
谢谢