在观看了这些关于 JS 事件循环和在浏览器中渲染的演讲之后(事件循环到底是什么?和 Web 浏览器事件循环、setTimeout、微任务、requestAnimationFrame...),我正在尝试什么类型的延迟会阻止浏览器中的渲染。
我正在测试这 4 种方法:
delayLoop
功能):这是我从演讲中了解到的行为。长任务会占用调用堆栈,因此浏览器无法将渲染推入堆栈。这会导致 UI 冻结,直到长任务完成为止。delayPromise
函数):这也具有类似的行为。这次,微任务(promise 的回调)使用长任务占用调用堆栈,这会推迟渲染任务直到完成。delayPromiseReturn
函数):这也具有类似的行为。虽然我不明白的是为什么func
的日志没有立即打印。我原本期望 func
能够完成,并在堆栈中运行承诺回调。delayTimeout
函数):我不理解这种行为。我原以为 UI 会在 5 秒后冻结,因为回调任务会占用调用堆栈并阻止渲染任务。相反,动画正常完成,回调任务也在后台正常完成(打印控制台日志),对渲染没有任何影响。function delayLoop() {
console.log('starting for loop')
for(let i = 0; i < 10000000000; i++) {}
console.log('ending for loop')
}
function delayPromise() {
Promise.resolve().then(function() {
console.log('starting promise')
for(let i = 0; i < 10000000000; i++) {}
console.log('ending promise')
})
}
function delayPromiseReturn() {
return new Promise(function(resolve) {
console.log('starting await')
for(let i = 0; i < 10000000000; i++) {}
console.log('ending await')
resolve()
})
}
function delayTimeout() {
setTimeout(function() {
console.log('starting timeout')
for(let i = 0; i < 10000000000; i++) {}
console.log('ending timeout')
}, 5000)
}
function func() {
console.log('starting delay func')
document.querySelector('.anim').classList.add('start')
/* delayLoop() */
/* delayPromise() */
/* delayPromiseReturn() */
delayTimeout()
console.log('ending delay func')
}
.anim {
height: 50px;
width: 50px;
background-color: blue;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(90deg);
}
}
.start {
animation: rotation 1s linear 10;
}
<button onclick="func()">Click</button>
<div class="anim"></div>
对 Promise return (
delayPromiseReturn
) 和 setTimeout (delayTimeout
) 行为有什么解释吗?如果我对其他点的理解有错误,请纠正我。
CSS 和图像动画不会被 JS 屏蔽,所以你会看到它们正常运行。