首頁 web前端 js教程 詳解javascript瀏覽器的事件循環機制

詳解javascript瀏覽器的事件循環機制

Oct 20, 2018 pm 04:15 PM
es6 javascript node.js

這篇文章帶給大家的內容是關於詳解javascript瀏覽器的事件循環機制,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

拋在前面的問題:

單執行緒如何做到非同步

事件循環的過程是怎樣的

macrotask 和microtask 是什麼,它們有何區別

單線程和非同步

提到js,就會想到單線程,非同步,那麼單線程是如何做到非同步的呢?概念先行,先要了解下單線程和非同步之間的關係。

js的任務分為同步和非同步兩種,它們的處理方式也不同,同步任務是直接在主執行緒上排隊執行,非同步任務則會被放到任務佇列中,若有多個任務(非同步任務)則要在任務佇列中排隊等待,任務佇列類似一個緩衝區,任務下一步會被移到呼叫堆疊(call stack),然後主執行緒執行呼叫堆疊的任務。

單執行緒是指js引擎中負責解析執行js程式碼的執行緒只有一個(主執行緒),即每次只能做一件事,而我們知道一個ajax請求,主執行緒在等待它回應的同時是會去做其它事的,瀏覽器先在事件表註冊ajax的回調函數,響應回來後回調函數被添加到任務隊列中等待執行,不會造成線程阻塞,所以說js處理ajax請求的方式是異步的。

總而言之,檢查呼叫堆疊是否為空,以及確定把哪個task加入呼叫堆疊的這個過程就是事件循環,而js實作非同步的核心就是事件循環。

呼叫堆疊和任務佇列

顧名思義,呼叫堆疊是一個堆疊結構,函數呼叫會形成一個棧幀,幀中包含了當前執行函數的參數和局部變數等上下文信息,函數執行完後,它的執行上下文會從堆疊中彈出。

下圖就是呼叫堆疊和任務佇列的關係圖

詳解javascript瀏覽器的事件循環機制

#事件循環

關於事件循環, 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的理解,光這樣看會有些晦澀難懂,結合事件循壞的機制理解清晰很多,下面這張圖可以說是介紹得非常清楚了。

詳解javascript瀏覽器的事件循環機制

總結起來,一次事件循環的步驟包括:

1. 檢查macrotask佇列是否為空,非空則到2,為空則到3
2. 執行macrotask中的一個任務
3. 繼續檢查microtask佇列是否為空,若有則到4,否則到5
4. 取出microtask中的任務執行,執行完成返回步驟3
5.執行視圖更新

mactotask & microtask的執行順序

詳解javascript瀏覽器的事件循環機制

讀完這麼多乾巴巴的概念介紹,不如看一段程式碼感受下

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~

詳解javascript瀏覽器的事件循環機制

首先,全域程式碼(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')
登入後複製

詳解javascript瀏覽器的事件循環機制

詳解javascript瀏覽器的事件循環機制

可以看到,结果1中requestAnimationFrame()是在一次事件循环后执行,而在结果2,它的执行则是在三次事件循环结束后。

总结

1、事件循环是js实现异步的核心

2、每轮事件循环分为3个步骤:

a) 执行macrotask队列的一个任务
b) 执行完当前microtask队列的所有任务
c) UI render

3、浏览器只保证requestAnimationFrame的回调在重绘之前执行,没有确定的时间,何时重绘由浏览器决定

以上是詳解javascript瀏覽器的事件循環機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles