js1*_*0cc 4 javascript event-loop html-rendering
我看到几篇文章说渲染步骤是在微任务之后。
我用这段代码测试它:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>test</p>
<script>
const p = document.querySelector('p');
p.textContent = 'text';
Promise.resolve().then(function microtask() {
debugger;
p.textContent = 'Promise';
});
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
这段代码似乎表明 UI在微任务运行之前重新渲染。
难道是我想错了?有没有什么好的例子表明渲染是在微任务运行之后进行的?
您可以通过查看事件循环处理模型来简单地证明这一点。解释一下它的当前状态,同时省略我们不感兴趣的几个步骤:
因此,很明显,微任务是在渲染发生之前执行的。
还没有被说服吗?
这是一个仅使用微任务就会阻塞 UI 5 秒的代码片段。在释放此锁之前,页面内容不会被渲染:
// We wrap our code in a 0 timeout and two rAF levels
// to be sure the initial rendering of the page did occur
setTimeout( () => {
requestAnimationFrame( () => {
requestAnimationFrame( () => {
// Now we modify the DOM
document.querySelector( 'p' ).textContent = "modified";
// and we start locking the UI using a Promise chain
const start = performance.now();
(function lockUI() { // IIFE
if( performance.now() - start < 5000 ) {
// recursive Promise chaining
// all these promises will get executed before the next rendering
// and block the UI rendering
// even though we were in an rAF callback!
return Promise.resolve()
.then( lockUI );
}
} )();
} );
} );
}, 0 );Run Code Online (Sandbox Code Playgroud)
<p>Initial (please wait 5s)</p>Run Code Online (Sandbox Code Playgroud)
细心的读者会注意到,这个脚本甚至没有将微任务排队到事件循环的第7步,而是排队到11.12 交错微任务检查点。
这只会更好地巩固实际渲染仅在步骤11.15完成的观点,并且之前的任何操作实际上都会延迟它。
因此,在您的测试用例中,永远不应该渲染“文本” ,因为通过调用Promise.resolve().then()您实际上会对微任务进行排队,从事件循环的角度来看,这实际上与这里的同步操作相同,因为排队之后没有任何事情发生。
但在某些情况下,您仍然可以看到渲染的文本,即浏览器进入旋转事件循环算法。如果浏览器面临一个长任务并决定可以执行此算法,则可能会发生这种情况,这将允许即使仍然运行一个长任务也可以执行渲染步骤。
例如,每当您启动诸如alert()或prompt()等模式时,Firefox 都会执行此操作。
所以在 Firefox 中,这个片段实际上会渲染文本text,Chrome 在这里不会调用这个算法,所以它不会渲染任何东西,甚至不会渲染初始的test:
const p = document.querySelector('p');
p.textContent = 'text';
Promise.resolve().then(function microtask() {
alert();
p.textContent = 'Promise';
});Run Code Online (Sandbox Code Playgroud)
<p>test</p>Run Code Online (Sandbox Code Playgroud)
然而 Chrome确实用debugger. 所以这个关键字不会阻止渲染,这就是为什么你会看到text正在渲染。
| 归档时间: |
|
| 查看次数: |
1199 次 |
| 最近记录: |