你能找出下面兩個程式碼片段的差異嗎:
function handleClick1() { setTimeout(handleClick1, 0); } function handleClick2() { Promise.resolve().then(handleClick2); }
如果您無法確定選擇其中一個的含義,那麼這篇部落格文章將教您一些新知識。
setTimeout 用來安排在一定時間後回調。 Promise.resolve().then 會有效地做同樣的事情,但內部兩者是不同的。後者返回一個已經解決的承諾。對該 Promise 呼叫 then(callback) 將安排執行回呼。
所以上述兩個函數都以最小的延遲遞歸地呼叫自己。不同之處在於,來自 setTimeout 的回呼被放置在巨集任務佇列中,而來自 Promise.then() 的回呼則被放置在微任務佇列中。事件循環如何處理這兩個佇列中的項目是上面兩個程式碼片段的差異。
事件循環所做的就是當有任務要執行時,它會執行這些任務,然後休眠並等待其他任務。
巨集任務(或簡稱任務)包含負責工作的函數,例如:
除此之外...
執行從任務佇列中選取的任務後,事件循環會執行微任務檢查點。其演算法類似:
While microtask queue is not empty, pick the oldest task from microtask queue and execute it.
這意味著,如果一個微任務將另一個微任務排入佇列,則該任務將在下一個巨集任務之前執行。而且由於 UI 渲染是一個巨集任務,它永遠不會被事件循環執行。
這是上述內容的示範:JS Bin demo。無限動畫正在運行。如果我們觸發handleClick1,那麼我們會向主線程添加一些處理,但動畫仍然可以正確渲染。但是如果我們觸發handleClick2,動畫就會停止。
我新增了變數totalCount,這樣我們就可以在頁面崩潰之前中斷。但值得注意的是,一旦 microTask 循環啟動,UI 將在一段時間內變得無回應。因為渲染、回應 DOM 等任務只會在 microtask 佇列為空後才會執行。
這使得上面程式碼片段中的handleClick1成為更安全的選擇。希望這篇部落格有助於解釋微任務和巨集任務之間的一個根本區別。
以上是UI 阻塞行為:微任務與巨集任務的詳細內容。更多資訊請關注PHP中文網其他相關文章!