這篇文章帶給大家的內容是關於詳解javascript瀏覽器的事件循環機制,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
拋在前面的問題:
單執行緒如何做到非同步
事件循環的過程是怎樣的
macrotask 和microtask 是什麼,它們有何區別
單線程和非同步
提到js,就會想到單線程,非同步,那麼單線程是如何做到非同步的呢?概念先行,先要了解下單線程和非同步之間的關係。
js的任務分為同步和非同步兩種,它們的處理方式也不同,同步任務是直接在主執行緒上排隊執行,非同步任務則會被放到任務佇列中,若有多個任務(非同步任務)則要在任務佇列中排隊等待,任務佇列類似一個緩衝區,任務下一步會被移到呼叫堆疊(call stack),然後主執行緒執行呼叫堆疊的任務。
單執行緒是指js引擎中負責解析執行js程式碼的執行緒只有一個(主執行緒),即每次只能做一件事,而我們知道一個ajax請求,主執行緒在等待它回應的同時是會去做其它事的,瀏覽器先在事件表註冊ajax的回調函數,響應回來後回調函數被添加到任務隊列中等待執行,不會造成線程阻塞,所以說js處理ajax請求的方式是異步的。
總而言之,檢查呼叫堆疊是否為空,以及確定把哪個task加入呼叫堆疊的這個過程就是事件循環,而js實作非同步的核心就是事件循環。
呼叫堆疊和任務佇列
顧名思義,呼叫堆疊是一個堆疊結構,函數呼叫會形成一個棧幀,幀中包含了當前執行函數的參數和局部變數等上下文信息,函數執行完後,它的執行上下文會從堆疊中彈出。
下圖就是呼叫堆疊和任務佇列的關係圖
#事件循環
關於事件循環, HTML規範的介紹
There must be at least one event loop per user agent, and at most
one event loop per unit of related similar-origin browsing contexts.
An event loop has one or more task queues.
Each task is defined as coming from a specific task source.
從規範理解,瀏覽器至少有一個事件循環,一個事件循環至少有一個任務佇列(macrotask),每個外任務都有自己的分組,瀏覽器會為不同的任務群組設定優先權。
macrotask & microtask
規格有提到兩個概念,但沒有詳細介紹,查閱一些資料大概可總結如下:
macrotask:包含執行整體的js程式碼,事件回調,XHR回調,定時器(setTimeout/setInterval/setImmediate),IO操作,UI render
microtask:更新應用程式狀態的任務,包括promise回調,MutationObserver,process.nextTick,Object.observe
其中setImmediate和process.nextTick是nodejs的實現,在nodejs篇會詳細介紹。
事件處理過程
關於macrotask和microtask的理解,光這樣看會有些晦澀難懂,結合事件循壞的機制理解清晰很多,下面這張圖可以說是介紹得非常清楚了。
總結起來,一次事件循環的步驟包括:
1. 檢查macrotask佇列是否為空,非空則到2,為空則到3
2. 執行macrotask中的一個任務
3. 繼續檢查microtask佇列是否為空,若有則到4,否則到5
4. 取出microtask中的任務執行,執行完成返回步驟3
5.執行視圖更新
mactotask & microtask的執行順序
讀完這麼多乾巴巴的概念介紹,不如看一段程式碼感受下
console.log('start') setTimeout(function() { console.log('setTimeout') }, 0) Promise.resolve().then(function() { console.log('promise1') }).then(function() { console.log('promise2') }) console.log('end')
列印台輸出的log順序是什麼?結合上述的步驟分析,係不繫so easy~
首先,全域程式碼(main())壓入呼叫堆疊執行,列印start;
接下來setTimeout壓入macrotask佇列,promise.then回呼放入microtask佇列,最後執行console.log('end'),列印出end;
至此,呼叫堆疊中的程式碼執行完成,回顧macrotask的定義,我們知道全域程式碼屬於macrotask,macrotask執行完,那接下來就是執行microtask佇列的任務了,執行promise回呼印出promise1;
promise回调函数默认返回undefined,promise状态变为fullfill触发接下来的then回调,继续压入microtask队列,event loop会把当前的microtask队列一直执行完,此时执行第二个promise.then回调打印出promise2;
这时microtask队列已经为空,从上面的流程图可以知道,接下来主线程会去做一些UI渲染工作(不一定会做),然后开始下一轮event loop,执行setTimeout的回调,打印出setTimeout;
这个过程会不断重复,也就是所谓的事件循环。
视图渲染的时机
回顾上面的事件循环示意图,update rendering(视图渲染)发生在本轮事件循环的microtask队列被执行完之后,也就是说执行任务的耗时会影响视图渲染的时机。通常浏览器以每秒60帧(60fps)的速率刷新页面,据说这个帧率最适合人眼交互,大概16.7ms渲染一帧,所以如果要让用户觉得顺畅,单个macrotask及它相关的所有microtask最好能在16.7ms内完成。
但也不是每轮事件循环都会执行视图更新,浏览器有自己的优化策略,例如把几次的视图更新累积到一起重绘,重绘之前会通知requestAnimationFrame执行回调函数,也就是说requestAnimationFrame回调的执行时机是在一次或多次事件循环的UI render阶段。
以下代码可以验证
setTimeout(function() {console.log('timer1')}, 0) requestAnimationFrame(function(){ console.log('requestAnimationFrame') }) setTimeout(function() {console.log('timer2')}, 0) new Promise(function executor(resolve) { console.log('promise 1') resolve() console.log('promise 2') }).then(function() { console.log('promise then') }) console.log('end')
可以看到,结果1中requestAnimationFrame()是在一次事件循环后执行,而在结果2,它的执行则是在三次事件循环结束后。
总结
1、事件循环是js实现异步的核心
2、每轮事件循环分为3个步骤:
a) 执行macrotask队列的一个任务
b) 执行完当前microtask队列的所有任务
c) UI render
3、浏览器只保证requestAnimationFrame的回调在重绘之前执行,没有确定的时间,何时重绘由浏览器决定
以上是詳解javascript瀏覽器的事件循環機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

WebStorm Mac版
好用的JavaScript開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

記事本++7.3.1
好用且免費的程式碼編輯器