簡體   English   中英

UI 更改事件被阻止

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM