一文告訴你 Event Loop 是什么?

?

Event Loop 也叫做“事件循環”,它其實與 JavaScript 的運行機制有關。

JS初始設計

JavaScript 在設計之初便是單線程,程序運行時,只有一個線程存在,在特定的時候只能有特定的代碼被執行。這和 JavaScript 的用途有關,它是一門瀏覽器腳本語言,通常是用來操作 DOM 的,如果是多線程,一個線程進行了刪除 DOM 操作,另一個添加 DOM,此時該如何處理?所以 JavaScript 在設計之初便是單線程的。

雖然 HTML5 增加了?Web Work?可用來另開一個線程,但是該線程仍受主線程的控制,所以 JavaScript 的本質依然是單線程

線程和進程

進程和線程是操作系統中的概念,在操作系統中,一個任務就是一個進程,比如你在電腦上打開了一個瀏覽器來觀看視頻,便是打開了一個瀏覽器進程,此時又想記錄視頻中的重要信息,于是你打開了備忘錄,這便是一個備忘錄進程,系統會為每個進程分配它所需要的地址空間,數據,代碼等系統資源。如果把一個進程看做一個小的車間,車間里有很多工人,有的負責操作機器,有的負責搬運材料,每個工人可以看做一個線程,線程可以共享進程的資源。可以說,線程是進程的最小單位,一個進程可以包含多個線程。

執行棧和任務隊列

單線程的 JavaScript 一段一段地執行,前面的執行完了,再執行后面的,試想一個,如果前一個任務需要執行很久,比如接口請求、I/O 操作,此時后面的任務只能干巴巴地等待么?干等不僅浪費了資源,而且頁面的交互程度也很差。JavaScript 意識到了這個問題,他們將任務分成了同步任務和異步任務,對于二者有不同的處理。

JavaScript 在運行時會將變量存放在堆(heap)和棧(stack)中,堆中通常存放著一些對象,而變量及對象的指針則存放在棧中。JavaScript 在執行時,同步任務會排好隊,在主線程上按照順序執行,前面的執行完了再執行后面的,排隊的地方叫執行棧(execution context stack)。JavaScript 對異步任務不會停下來等待,而是將其掛起,繼續執行執行棧中的同步任務,當異步任務有返回結果時,異步任務會加入與執行棧不一樣的隊列,即任務隊列(task queue),所以任務隊列中存放的是異步任務執行完成后的結果,通常是回調函數。

當執行棧的同步任務已經執行完成,此時主線程閑下來,它便會去查看任務隊列是否有任務,如果有,主線程會將最先進入任務隊列的任務加入到執行棧中執行,執行棧中的任務執行完了之后,主線程便又去任務隊列中查看是否有任務可執行。主線程去任務隊列讀取任務到執行棧中去執行,這個過程是循環往復的,這便是?Event Loop,事件循環。

網上有張流傳甚廣的圖對這一過程進行了總結,在圖中我們可以看到,JavaScript 在運行時產生了堆和棧,ajax、setTimeout 等異步任務被掛起,異步任務的返回結果加入任務隊列,主線程會循環往復地讀取任務隊列中的任務,加入執行棧中執行。

?

(JavaScript 運行機制,圖片來源于網絡)

宏任務與微任務

異步任務有更深一層的劃分,它們是宏任務(macro task)和微任務(micro task),二者的執行順序也有差別。在上面我們講到異步任務的結果會進入任務隊列中,對于不同的事件類型,宏任務會加入宏任務隊列,微任務會加入微任務隊列。在執行棧中的同步任務執行完成后,主線程會先查看任務隊列中的微任務,如果有沒有,則去宏任務隊列中取出最前面的一個事件加入執行棧中執行;如果有,則將所有在微任務隊列中的事件依次加入執行棧中執行,直到所有事件執行完成后,再去宏任務中取出最前面的一個事件加入執行棧,如此循環往復。

由此我們可以得出結論,主線程總是會先查看微任務隊列,等到微任務隊列中的事件都處理完成后,再去宏任務隊列中添加一個事件到任務棧中執行。

常見的宏任務有 setTimeout,setInterval;常見的微任務有 new Promise。

代碼例子體驗

console.log(1)setTimeout(function() {console.log(2)new Promise(function(resolve) {console.log(3)resolve(4)}).then(function(num) {console.log(num)})
}, 300)new Promise(function(resolve) {console.log(5)resolve(6)
}).then(function(num) {console.log(num)
})setTimeout(function() {console.log(7)
}, 400)

我們一步步來分析上面的執行順序,當程序開始執行時,首先打印出 1,然后遇到了 setTimeout,主程序將它掛起,300 毫秒后它的回調函數進入宏任務隊列,我們記做 setTimeout1。隨后遇到了 new Promise,resolve 部分是同步執行的,所以會打印出 5,then 中的回調函數進入微任務隊列,我們暫時記做 promise1。最后是 setTimeout,同理在 400 毫秒后加入了宏任務隊列,我們記做 setTimeout2。

此時任務隊列的情況如下:

宏任務

微任務

setTimeout1

promise1

setTimeout2

?

執行棧中的同步任務執行完成后,主線程查看任務隊列時發現存在微任務,于是把 promise1 執行了,打印出 6。此時微任務隊列已經空了,于是開始查看宏任務隊列,將 setTimeout1 的回調函數加入任務棧開始執行,于是首先打印出 2,之后是 3,再將 then 中的回調函數加入微任務隊列,我們記做 promise2。

此時任務隊列的情況如下:

宏任務

微任務

setTimeout2

promise2

此時執行棧也空了,于是將微任務 promise2 加入執行棧,打印出 4。此時微任務已經執行完,再查看宏任務隊列,于是執行 setTimeout2,打印出 7。

所以代碼中的輸出順序是 1,5,6,2,3,4,7。

注意,主線程對微任務的讀取是逐個讀取,直到微任務隊列為空,再讀取宏隊列,對宏任務隊列的讀取在一個循環中只讀取一個。

小結

我們了解了 JavaScript 的運行機制,它是單線程的。JavaScript 中的任務可分為同步任務和異步任務,同步任務總是先進入執行棧中執行,異步任務會被掛起,直到有結果返回時,異步任務會進入任務隊列中等待主線程讀取執行。當執行棧為空時,主線程便會循環往復地讀取任務隊列中的事件,進入執行棧執行,這個過程叫 Event Loop。主線程對任務隊列的讀取也有先后之分,首先會去查找微任務,微任務隊列的事件都執行完畢后,再讀取最前面的宏任務進行執行,執行完再讀取微任務隊列,這個過程也是循環往復的。

?

轉載于:https://www.cnblogs.com/Joe-and-Joan/p/10687551.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449259.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449259.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449259.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot -Shiro配置多Realm

2019獨角獸企業重金招聘Python工程師標準>>> 核心類簡介 xxxToken:用戶憑證 xxxFilter:生產token,設置登錄成功,登錄失敗處理方法,判斷是否登錄連接等 xxxRealm:依據配置的支持Token來認證用戶信…

idea工具debug斷點紅色變成灰色

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 沒事別瞎點,禁用了斷點當然不走了 轉自:https://blog.csdn.net/anlve512/article/details/54583469

2020-3-20前端題目

題目一&#xff1a; 判斷checked復選框是否有被選中 <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <script> window.onload () > {let odivdocument.getElementById("ant");let ckdocument.getElementById(&…

上班族如何當老板 五大模式任你選

中國教育在線訊 辭職創業&#xff0c;還是維持現在穩定的工作?這個是很多上班族都糾結過的問題&#xff0c;一邊是穩定的工作和收入&#xff0c;一邊是創業當老板的誘惑&#xff0c;真是很難選擇。 其實&#xff0c;如果安排合理是可以“魚與熊掌”兼得的&#xff0c;沈陽市古…

利用 Linux tap/tun 虛擬設備寫一個 ICMP echo 程序

利用 Linux tap/tun 虛擬設備寫一個 ICMP echo 程序 前面兩篇文章已經介紹過 tap/tun 的原理和配置工具。這篇文章通過一個編程示例來深入了解 tap/tun 的程序結構。 01 準備工作 首先通過 modinfo tun 查看系統內核是否支持 tap/tun 設備驅動。 Copy[rootby ~]# modinfo tun f…

2020-3-21

題目一&#xff1a; JavaScript 獲取月份最后一天日期 月份最后一天日期可能是不同的&#xff0c;比如有的是30、有的是31還有的是28。 <!DOCTYPE html><html> <head> <meta charset" utf-8"> <script type"text/javascript"&…

正方形矩陣求對角線之和

nint(input()) a[] for i in range(n): #循環體里面加入input&#xff08;&#xff09;可以實現一共執行n次input&#xff08;&#xff09; lst[int(x) for x in input().split()]a.append(lst) #用列表解析&#xff0c;兩層列表代表行列&#xff0c;很巧妙的方法 w0 bl…

解決: Unable to connect to zookeeper server within timeout: 5000

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一個項目啟動不起來了&#xff0c;報錯如題&#xff1a; Caused by: org.I0Itec.zkclient.exception.ZkTimeoutException: Unable to c…

閑錢請看如何處理

買一點基金定投。基金是專家幫你理財。基金的起始資金最低單筆是1000元,定投200元起投 買基金到銀行或者基金公司都行。銀行能代理很多基金公司的業務&#xff0c;具體開戶找銀行理財專柜辦理。現在有些證券公司也有代理基金買賣的。在銀行開通網上銀行后網上購買一般收費上有優…

JAVA 數組元素的反轉

package Code411;/*數組元素的反轉本來[1,2,3,4]反轉后[4,3,2,1]1.對稱位置的元素交換2.對稱位子需要兩個索引3.int temp a&#xff1b;ab;btemp;4.什么時候停止交換&#xff08;1&#xff09;minmax (2)min>max */public class CodeArrayReverse { public static void m…

requests模塊相關用法

requests模塊 -1. 什么是requests模塊- python原生的一個基于網絡請求的模塊&#xff0c;模擬瀏覽器發起請求。 -2. 為什么使用requests模塊-1. 自動處理url編碼-2. 自動處理post請求參數-3. 簡化cookie和代理的操作-3. requests模塊如何被使用安裝&#xff1a; pip install re…

2020-3-22

題目一&#xff1a; JavaScript 天小時分鐘和秒倒計時 代碼與解析&#xff1a; <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <style type"text/css"> *{margin:0;padding:0;list-style:none; } body{font-size:…

TeamViewer13 -- 安裝、使用說明

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Teamviewer13是一款強大的遠程桌面控制工具&#xff0c;同時也是一款非常實用的共享文件傳輸工具&#xff0c;它擁有簡潔的界面以及方便快…

論程序員的自我修煉

摘要&#xff1a;軟件開發是個挑戰&#xff0c;尤其是對于那些完美主義的程序員。為了想要成為更好的程序員&#xff0c;總會開發出一些特別的功能&#xff0c;在軟件設計上想要做到零瑕疵&#xff0c;但事實上&#xff0c;完美的軟件設計是根本不存在的&#xff0c;試著讓你的…

利用 Charles Proxy 下載舊版本 iOS App

一、軟件準備 1、舊版本 iTunes1.IPSW Downloads&#xff1a;https://ipsw.me/2.百度網盤鏈接&#xff1a;https://pan.baidu.com/s/1PO9Z12o-rqZ_JG68zRqEnA 提取碼&#xff1a;fe1v 2、抓包工具 Charles Proxy1.Charles官網鏈接&#xff1a;https://www.charlesproxy.com/2.百…

禪道8.2-9.2.1注入GetShell

漏洞分析附上某老哥的漏洞分析&#xff0c;來了解下原理。 漏洞利用查看版本&#xff1a;訪問Url&#xff1a;http://127.0.0.1/zentao/index.php?modegetconfig即可獲取禪道的版本號以及一些其他的信息&#xff0c;目前漏洞存在于v8.2~v9.2確定版本號之后&#xff0c;我們就…

2020-3-23

題目一&#xff1a; JavaScript 復選框全選和全不選 <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <style type"text/css"> body{font-size:12px;} ul{list-style:none} </style> <script type"te…

Maven 依賴-鏡像倉庫替換為 -- 阿里云鏡像倉庫(飛快實現 pom 引入)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 在本地 maven 的 setting 配置文件中加上阿里云鏡像地址就行了&#xff1a; 新增配置內容&#xff1a; <!-- 阿里鏡像倉庫 --><…

cmake 常用命令

1. 使用日期 # 獲取時間 string(TIMESTAMP DATE_TIME "%y-%m-%d %H:%M")# 獲取日期 string(TIMESTAMP DATE_VERSION "%m%d") 轉載于:https://www.cnblogs.com/ziyu-trip/p/10697309.html

愛屋吉屋病死后,鏈家、中原、我愛我家們卻哭不得笑不得

作為互聯網房產中介最快成長為行業獨角獸的愛屋吉屋&#xff0c;還是沒能迎來開春之暖&#xff0c;于2019年2月19日便停止了運營。對于這個享有創造中國房市273天四輪融資的奇跡、估值超過10億美元的速成獨角獸、一代“革命者”、創造世界紀錄的互聯網房產神話等多個美譽企業的…