Javascript前端事件循環(huán)機(jī)制詳細(xì)講解
一、消息隊(duì)列和事件循環(huán)
1.單線程處理機(jī)制
如果有一些確定好的任務(wù),可以使用一個(gè)單一的線程來按順序處理這些事情,等到所有任務(wù)執(zhí)行完畢之后,退出當(dāng)前線程。
int main(){ int a, b; cin >> a; cin >> b; cout << a + b << endl; return 0; }
2.事件循環(huán)機(jī)制
在單線程處理機(jī)制中,如果需要接收并處理新的任務(wù),需要引入事件循環(huán)機(jī)制。
int main(){ int a, b; while (true) { cin >> a; cin >> b; cout << a + b; } return 0; }
3.消息隊(duì)列
如果需要處理其他線程的任務(wù),需要使用消息隊(duì)列。
消息隊(duì)列是一種數(shù)據(jù)結(jié)構(gòu),存放要執(zhí)行的任務(wù)。它符合隊(duì)列“先進(jìn)先出”的特點(diǎn),新增任務(wù)添加到隊(duì)列的尾部,隊(duì)列頭部取出任務(wù)。
主線程在執(zhí)行過程中,通過事件循環(huán)機(jī)制從消息隊(duì)列中讀取任務(wù)。
4.IO線程
在瀏覽器的渲染進(jìn)程中,專門有一個(gè)IO線程用來接收其他進(jìn)程傳進(jìn)來的消息。接收到消息后,會(huì)將這些消息組裝成任務(wù)發(fā)送給主線程放入消息隊(duì)列中。
5.頁面使用單線程的缺點(diǎn)
(1)如何處理高優(yōu)先級(jí)的任務(wù)
(2)如何解決單個(gè)任務(wù)執(zhí)行時(shí)長(zhǎng)過久的問題
二、setTimeout
1.瀏覽器怎么實(shí)現(xiàn) setTimeout
在瀏覽器中,除了普通的消息隊(duì)列之外,還有一個(gè)延遲任務(wù)的消息隊(duì)列,包括了定時(shí)器和 Chromium 內(nèi)部一些需要延遲執(zhí)行的任務(wù)。所以當(dāng)通過JavaScript創(chuàng)建定時(shí)器時(shí),渲染進(jìn)程會(huì)將該定時(shí)器的回調(diào)任務(wù)添加到延遲隊(duì)列中。
加入延遲隊(duì)列之后,事件循環(huán)線程中的執(zhí)行過程就變成了,先執(zhí)行一次正常消息隊(duì)列中的任務(wù),如果當(dāng)前任務(wù)中有延遲事件,將該延遲事件加入到延遲任務(wù)消息隊(duì)列,在該任務(wù)執(zhí)行完之后,依次執(zhí)行延遲隊(duì)列中的到期任務(wù)。然后依次循環(huán)執(zhí)行下去。
2.使用setTimeout的一些注意事項(xiàng)
(1)當(dāng)前任務(wù)執(zhí)行時(shí)間過長(zhǎng)會(huì)影響定時(shí)器任務(wù)的執(zhí)行。
(2)如果setTimeout存在嵌套調(diào)用,那么系統(tǒng)會(huì)設(shè)置最短時(shí)間間隔為4毫秒
(3)未激活的頁面,setTimeout執(zhí)行最小間隔是1000毫秒
(4)延時(shí)執(zhí)行時(shí)間有最大值
三、宏任務(wù)和微任務(wù)
1.宏任務(wù)
渲染事件(如解析DOM、計(jì)算布局、繪制頁面)
用戶交互事件(點(diǎn)擊、滾動(dòng)、縮放)
JavaScript腳本執(zhí)行事件
網(wǎng)絡(luò)請(qǐng)求、文件讀寫完成
(1)事件循環(huán)機(jī)制
- 先從消息隊(duì)列中選出一個(gè)最老的任務(wù),這個(gè)任務(wù)稱為oldestTask
- 然后循環(huán)系統(tǒng)記錄任務(wù)開始執(zhí)行時(shí)間,并將oldestTask設(shè)置為當(dāng)前正在執(zhí)行的任務(wù)
- 當(dāng)任務(wù)執(zhí)行完成之后,刪除當(dāng)前正在執(zhí)行的任務(wù),并從消息隊(duì)列中刪除oldestTask
- 最后統(tǒng)計(jì)執(zhí)行完成的時(shí)長(zhǎng)等信息
2.微任務(wù)
微任務(wù)就是一個(gè)需要異步執(zhí)行的函數(shù),執(zhí)行時(shí)機(jī)是在主函數(shù)執(zhí)行結(jié)束之后、當(dāng)前宏任務(wù)結(jié)束之前。
- Dom添加、刪除等操作
- Promise resolve和reject
(1)微任務(wù)和宏任務(wù)是綁定的,每個(gè)宏任務(wù)在執(zhí)行時(shí),會(huì)創(chuàng)建自己的微任務(wù)隊(duì)列。
(2)微任務(wù)的執(zhí)行時(shí)長(zhǎng)會(huì)影響到當(dāng)前宏任務(wù)的時(shí)長(zhǎng)
(3)在一個(gè)宏任務(wù)中,分別創(chuàng)建一個(gè)用于回調(diào)的宏任務(wù)和微任務(wù),無論什么情況下,微任務(wù)都早于宏任務(wù)執(zhí)行。
到此這篇關(guān)于Javascript前端事件循環(huán)機(jī)制詳細(xì)講解的文章就介紹到這了,更多相關(guān)Javascript事件循環(huán)機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序自定義組件傳值 頁面和組件相互傳數(shù)據(jù)操作示例
這篇文章主要介紹了微信小程序自定義組件傳值 頁面和組件相互傳數(shù)據(jù)操作,結(jié)合實(shí)例形式分析了微信小程序常見傳值操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-05-05vscode使用Prettier Code插件的詳細(xì)教程
這篇文章主要介紹了vscode使用Prettier Code插件的詳細(xì)教程,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09uniapp踩坑實(shí)戰(zhàn)之文件查找失敗:'uview-ui'?at?main.js解決辦法
這篇文章主要給大家介紹了關(guān)于uniapp踩坑實(shí)戰(zhàn)之文件查找失敗:'uview-ui'?at?main.js的解決辦法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12利用js判斷數(shù)據(jù)是否是數(shù)組或字符串的常見方法
這篇文章主要給大家介紹了關(guān)于利用js判斷數(shù)據(jù)是否是數(shù)組或字符串的常見方法,其實(shí)有很多方法可以判斷數(shù)據(jù)是否是數(shù)組或字符串,需要的朋友可以參考下2023-07-07javascript的onchange事件與jQuery的change()方法比較
本來是想添加文本框文本內(nèi)容改變事件動(dòng)作的,結(jié)果找了許多這方面的javascript代碼都不如意。2009-09-09JS代碼實(shí)現(xiàn)根據(jù)時(shí)間變換頁面背景效果
這篇文章主要介紹了JS代碼實(shí)現(xiàn)根據(jù)時(shí)間變換頁面背景效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友一起看下吧2016-06-06layui時(shí)間控件選擇時(shí)間范圍的實(shí)現(xiàn)方法
今天小編就為大家分享一篇layui時(shí)間控件選擇時(shí)間范圍的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09Svelte框架實(shí)現(xiàn)表格協(xié)同文檔的示例
本文主要介紹了Svelte框架實(shí)現(xiàn)表格協(xié)同文檔的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01