日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

深入理解JavaScript的事件循环

發布時間:2023/12/18 javascript 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解JavaScript的事件循环 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近閱讀《高性能JavaScript》時,第六章談到“通過定時器將JavaScript執行代碼的控制權先讓給瀏覽器用于更新UI狀態,然后再將控制權交回給JavaScript代碼,這樣就可以使得頁面更為流暢”,就聯想到了之前理解的事件循環。

這篇文章就是為了解釋為什么這么做可以提升頁面的流暢度。

事件循環(Event Loop)

單線程的JavaScript

總所周知,JavaScript語言的一大特點就是單線程,也就是說在一個時間段里,JavaScript只能做一件事情(瀏覽器是多線程)。 多線程可以實現應用的并行處理,從而以更高的CPU利用率提高整個應用程序的性能和吞吐量

但是JavaScript卻以單線程進行,為什么呢?

JavaScript是瀏覽器腳本語言,用于與用戶交互以及操作DOM。 考慮如下情況,如果有兩個并發的操作,對同一個DOM節點分別進行刪除和修改樣式,此時瀏覽器就無法決定到底采用哪個線程的操作。類似數據庫,我們可以采用“鎖”來處理并發,但是這會平添復雜度。所以,JavaScript語言沒有支持多線程操作。 那又考慮這種情況,既然JavaScript是單線程,在某一時刻內只能執行特定的一個任務,并且會阻塞其它任務執行。那么如果用戶觸發了一個非常耗時的I/O操作,那么按道理后續的所有操作都得等到I/O操作完成后方可進行。但是,事實上,后續的任務不必等待這個耗時的I/O操作完成,原因就是JavaScript與生俱來的異步和回調

而這背后恰好就是本文的主題——————事件循環

定義

事件循環包含了至少兩個任務隊列,宏任務隊列和微任務隊列。

宏任務

宏任務包含創建文檔對象、解析HTML、執行主線JavaScript代碼、更改當前URL以及各種事件,例如頁面加載、輸入、網絡事件和定時器等等。宏任務運行完成后,瀏覽器繼續其他的任務調度,如重新渲染頁面或者垃圾回收。

微任務

微任務包括promise、回調函數、DOM發生變化等。微任務更新應用程序的狀態,必須在瀏覽器任務繼續執行其他任務(渲染UI視圖或者進行下一個宏任務)之前執行。

兩個基本原則

  • 一次處理一個任務
  • 一個任務開始直到運行完成,不會被其他任務中斷
  • 無論是宏任務隊列還是微任務隊列,二者在同一時刻都只執行一個任務,不過二者也有重要的區別:在一次循環中,最多處理一個宏任務,而微任務隊列中所有的微任務都會被處理

    ?

    在微任務隊列清空后,事件循環會檢查當前是否需要重新渲染UI,如果需要則渲染UI視圖。

    補充

  • 兩個任務隊列都是獨立于事件循環的,這意味著任務隊列的添加發生在事件循環外。
  • 所有微任務都會在下一次渲染前完成,目的是在渲染前更新應用程序狀態。
  • 瀏覽器會嘗試以每秒渲染60次頁面,以達到每秒60幀的速度。所以,一次循環最理想的時間應該不超過16ms。
  • 瀏覽器完成頁面渲染后,進入下一輪事件循環迭代后,可能出現3種情況
  • 如果事件循環執行到“is rendering needed”且瀏覽器處于另一個16ms結束之前(即瀏覽器尚未自動觸發頁面渲染時),瀏覽器可能不會選擇在當前的時間循環中執行更新UI操作,因為更新UI是一個復雜且耗性能的操作。
  • 如果事件循環執行到“is rendering needed”且瀏覽器剛好離上一次渲染16ms左右時(即瀏覽器即將自動觸發頁面渲染時),此時瀏覽器會進行UI更新。
  • 執行下一個事件循環耗時超過16ms,瀏覽器將無法以目標幀率重新渲染頁面,且UI無法被更新。如果延遲不大是很難察覺到,但是,如果有非常耗時的操作,這個時候用戶會覺得網頁十分卡頓,甚至瀏覽器會提示“無響應腳本”。
  • 前情回顧

    現在,用事件循環和簡單的例子來分析《高性能的JavaScript》中的那句話。 需求:給包含1000個數字的數組中的每個元素取絕對值(假設對一個數字進行需求操作耗時1ms)。

    情況1(不使用定時器): 由于JavaScript主線程代碼屬于宏任務的一種,所以一次事件循環需要處理1000個數字,所以1s事件循環才進行到UI更新階段,但是由于耗時過長,UI狀態不會被更新,頁面出現卡頓甚至堵塞。

    情況2(使用定時器): 將一次處理1000個數字的任務分割為20個每次處理50個數字的任務。由于定時器是宏任務的一種,所以一次事件循環只處理50個數字,由于此時微任務隊列為空,所以50ms后事件循環進行到UI更新階段,然后根據情況進行UI渲染,頁面未出現卡頓或者堵塞。

    當然,如果只是單純的處理數據,我們可以考慮使用Web Workers

    總結

  • JavaScript是單線程的,同一時刻是只能執行一個任務。
  • 事件循環包含一個宏任務隊列和至少一個微任務隊列。事件循環一次迭代,至多執行一個宏任務但是會執行完所有的微任務。
  • Web應用越復雜,積極主動管理UI線程就越重要,即使JavaScript代碼很重要,也不能影響用戶體驗
  • 轉載于:https://www.cnblogs.com/LianML/p/9244729.html

    總結

    以上是生活随笔為你收集整理的深入理解JavaScript的事件循环的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。