關(guān)于js的事件循環(huán)機(jī)制剖析
前言
眾所周知, JavaScript是單線(xiàn)程這一核心,可是瀏覽器又能很好的處理異步請(qǐng)求,那么到底是為什么呢?其中的原理與事件循環(huán)機(jī)制大有關(guān)系。
在探索事件循環(huán)之前,我們得先了解瀏覽器執(zhí)行線(xiàn)程~~
瀏覽器的渲染進(jìn)程是多線(xiàn)程的,瀏覽器每一個(gè)tab標(biāo)簽都代表一個(gè)獨(dú)立的進(jìn)程,其中瀏覽器內(nèi)核屬于瀏覽器多進(jìn)程中的一種,主要負(fù)責(zé)頁(yè)面渲染,腳本執(zhí)行,事件處理等。其包含的線(xiàn)程有以下幾種
GUI 渲染線(xiàn)程:負(fù)責(zé)渲染頁(yè)面,解析 HTML,CSS 構(gòu)成 DOM 樹(shù);
JS 引擎線(xiàn)程:解釋執(zhí)行代碼、用戶(hù)輸入和網(wǎng)絡(luò)請(qǐng)求;
事件處理線(xiàn)程:click、mouse等交互事件發(fā)生后將事件函數(shù)放入隊(duì)列;
定時(shí)器觸發(fā)線(xiàn)程:等時(shí)間結(jié)束后執(zhí)行函數(shù)推入任務(wù)隊(duì)列中;
http網(wǎng)絡(luò)請(qǐng)求線(xiàn)程:處理用戶(hù)的get、post請(qǐng)求,返回結(jié)果推入任務(wù)隊(duì)列中。
了解了瀏覽器渲染流程,還要了解JS的運(yùn)行機(jī)制。JS的運(yùn)行機(jī)制就是事件循環(huán)
執(zhí)行棧
JS運(yùn)行的環(huán)境稱(chēng)之為宿主環(huán)境。
執(zhí)行棧:call stack,一個(gè)數(shù)據(jù)結(jié)構(gòu),用于存放各種函數(shù)的執(zhí)行環(huán)境,每一個(gè)函數(shù)執(zhí)行之前,它的相關(guān)信息會(huì)加入到執(zhí)行棧。函數(shù)調(diào)用之前,創(chuàng)建執(zhí)行環(huán)境,然后加入到執(zhí)行棧;函數(shù)調(diào)用之后,銷(xiāo)毀執(zhí)行環(huán)境。
事件循環(huán)
js中所有的任務(wù)可以分為同步任務(wù)和異步任務(wù),同步任務(wù)是立即執(zhí)行的任務(wù),同步任務(wù)一般會(huì)直接進(jìn)入到主線(xiàn)程中執(zhí)行;而異步任務(wù),就是異步執(zhí)行的任務(wù),比如ajax網(wǎng)絡(luò)請(qǐng)求,setTimeout 定時(shí)函數(shù)等都屬于異步任務(wù),異步任務(wù)會(huì)通過(guò)任務(wù)隊(duì)列(先進(jìn)先出)的機(jī)制來(lái)進(jìn)行協(xié)調(diào)。同步和異步任務(wù)分別進(jìn)入不同的執(zhí)行環(huán)境,同步的進(jìn)入主線(xiàn)程,即主執(zhí)行棧,異步的進(jìn)入任務(wù)隊(duì)列。主線(xiàn)程內(nèi)的任務(wù)執(zhí)行完畢為空,會(huì)去任務(wù)隊(duì)列讀取對(duì)應(yīng)的任務(wù),推入主線(xiàn)程執(zhí)行。 這種不斷重復(fù)就是我們說(shuō)的 Event Loop (事件循環(huán))。具體流程如下圖。
在事件循環(huán)中,每進(jìn)行一次循環(huán)操作稱(chēng)為tick,每一次 tick 的任務(wù)鍵的步驟可以總結(jié)如下:1.執(zhí)行一個(gè)宏任務(wù)(棧中沒(méi)有就從事件隊(duì)列中獲?。?;2.執(zhí)行過(guò)程中如果遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中;3.宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行);4.當(dāng)前宏任務(wù)執(zhí)行完畢,開(kāi)始檢查渲染,然后GUI線(xiàn)程接管渲染;5.渲染完畢后,JS線(xiàn)程繼續(xù)接管,開(kāi)始下一個(gè)宏任務(wù)(從事件隊(duì)列中獲取)
宏任務(wù)主要包含:script( 整體代碼)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 環(huán)境)
微任務(wù)主要包含:Promise、MutaionObserver、process.nextTick(Node.js 環(huán)境)
事件循環(huán)例子
console.log('script start'); //整體 script 作為第一個(gè)宏任務(wù)進(jìn)入主線(xiàn)程,遇到 console.log,輸出 script start setTimeout(function() { console.log('setTimeout'); }, 0); //遇到 setTimeout,其回調(diào)函數(shù)被分發(fā)到宏任務(wù) Event Queue 中 Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); //遇到 Promise,其 then函數(shù)被分到到微任務(wù) Event Queue 中,記為 then1,之后又遇到了 then 函數(shù),將其分到微任務(wù) Event Queue 中,記為 then2 console.log('script end'); //遇到 console.log,輸出 script end
如此,Event Queue(事件隊(duì)列)中存在三個(gè)任務(wù):宏任務(wù):setTimeout 微任務(wù):then1、then2。執(zhí)行微任務(wù)首先then1,輸出 promise1, 然后執(zhí)行 then2,輸出 promise2,這樣就清空了所有微任務(wù)
執(zhí)行 setTimeout 任務(wù),輸出 setTimeout 至此,輸出的順序是:script start, script end, promise1, promise2, setTimeout
總結(jié):
JavaScript 是一門(mén)單線(xiàn)程語(yǔ)言,異步操作都是放到事件循環(huán)隊(duì)列里面,等待主執(zhí)行棧來(lái)執(zhí)行的,并沒(méi)有專(zhuān)門(mén)的異步執(zhí)行線(xiàn)程。
到此這篇關(guān)于js的事件循環(huán)機(jī)制的文章就介紹到這了,更多相關(guān)js事件循環(huán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)AOP詳解(面向切面編程,裝飾者模式)
下面小編就為大家分享一篇JavaScript實(shí)現(xiàn)AOP的方法(面向切面編程,裝飾者模式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12百度坐標(biāo)(BD09)、國(guó)測(cè)局坐標(biāo)(火星坐標(biāo),GCJ02)、和WGS84坐標(biāo)系之間的轉(zhuǎn)換
這篇文章主要介紹了百度坐標(biāo)(BD09)、國(guó)測(cè)局坐標(biāo)(火星坐標(biāo),GCJ02)、和WGS84坐標(biāo)系之間的轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下2016-02-02點(diǎn)擊按鈕彈出模態(tài)框的一系列操作代碼實(shí)例
這篇文章主要介紹了js彈出模態(tài)框方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03小程序webView實(shí)現(xiàn)小程序內(nèi)嵌H5頁(yè)面的全過(guò)程
在微信小程序中內(nèi)嵌H5頁(yè)面是一種常見(jiàn)的需求,因?yàn)镠5頁(yè)面具有靈活性和跨平臺(tái)性,可以彌補(bǔ)小程序原生代碼的不足,這篇文章主要給大家介紹了關(guān)于小程序webView實(shí)現(xiàn)小程序內(nèi)嵌H5頁(yè)面的相關(guān)資料,需要的朋友可以參考下2024-07-07js計(jì)算系統(tǒng)當(dāng)前日期是星期幾的方法
這篇文章主要為大家詳細(xì)介紹了js計(jì)算系統(tǒng)當(dāng)前日期是星期幾4種方法,需要的朋友可以參考下2016-07-07- 水平不高,不能也不想從太深的層次去講解這個(gè)東西,只是根據(jù)一段比較有代表性的代碼,結(jié)合執(zhí)行結(jié)果,從表象上粗淺地談?wù)劇?/div> 2010-12-12
最新評(píng)論