[英]UI change events being blocked
我有兩個元素,一個段落和一個按鈕。 單擊按鈕時,瀏覽器應使用p
標記呈現文本"Waiting"
,等待 3 秒,然后呈現文本"Done"
。 它運行但從未呈現文本"Waiting"
。
我知道這可以通過setTimeout
解決,但我試圖理解為什么文本"Waiting"
根本沒有出現。
HTML:
<p id="p">Ready</p>
<button id="button">Start</button>
Java腳本:
const pTag = document.getElementById('p');
const button = document.getElementById('button');
button.onclick = () => {
pTag.innerText = 'Waiting';
syncWaitSeconds(3)
pTag.innerText = 'Done';
};
function syncWaitSeconds(seconds = 3){
const start = Date.now();
const time = seconds * 1000
while (Date.now() - start <= time) {
// waiting 3 seconds
}
}
我正在學習 Javascript,我想知道為什么文本沒有顯示出來。 由於更改 innerText 不會返回承諾並且是同步的,它不應該先發生,然后等待 3 秒,最后呈現文本“完成”嗎?
這是因為您正在忙等待,也就是說,您的瀏覽器太忙了,總是比較這些日期,它根本無法更新 UI。 這是異步需求的一個很好的例子。 不僅僅是innerText
沒有刷新,而是整個 UI 在這種忙等待發生時沒有響應。
這就是為什么您需要通過setTimeout
異步執行此操作的原因。 沒有setTimeout
:
const pTag = document.getElementById('p'); const button = document.getElementById('button'); button.onclick = () => { pTag.innerText = 'Waiting'; syncWaitSeconds(3) pTag.innerText = 'Done'; }; function syncWaitSeconds(seconds = 3){ const start = Date.now(); const time = seconds * 1000 while (Date.now() - start <= time) { // waiting 3 seconds } }
<p id="p"></p> <button id="button">My Button</button>
使用setTimeout
:
const pTag = document.getElementById('p'); const button = document.getElementById('button'); button.onclick = () => { pTag.innerText = 'Waiting'; setTimeout(function() { pTag.innerText = 'Done'; }, 3000); };
<p id="p"></p> <button id="button">My Button</button>
我對此有更多解釋並在這里分享
我得到的解釋是有兩個線程,處理 Javascript 的 JS 主線程和處理 UI 更改(包括 CSS 更改)的瀏覽器繪制線程,並且兩者之間正在進行線程同步。
更改為“等待”的任務確實執行並且繪制線程應該處理它但它等待因為 JS 調用堆棧不為空。 因此,僅當 JS 代碼未運行時,JS 和 CSS 的 UI 更改才會發生。
在 syncWaitSecond 之后,線程同時渲染了“Waiting”和“Done”,但是它太快了以至於我們只能看到“Done”,或者可能在組合步驟中進行了一些優化,只渲染了“Done”,但這些變化只發生在JS 調用堆棧為空。
當我們使用 setTimeout 執行此操作時,調用堆棧立即為空並呈現“等待”。 3 秒后,setTimeout 返回堆棧,執行代碼將文本更改為“完成”。 此任務被添加到 UI 線程的隊列中,但 UI 線程將再次等待 JS 代碼完成,然后再繪制“完成”。 這些都是有趣的東西,讓我了解到在 JS 和瀏覽器領域有很多我不知道的東西。
瘋狂的是,如果您被阻止的 JS 代碼,甚至 CSS 更改(如在懸停時更改背景顏色)也不會起作用,因為這也由該繪畫線程處理,並將等待 JS 完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.