成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Event Loop

darkbug / 1728人閱讀

摘要:引擎線程,也稱為內(nèi)核,負(fù)責(zé)處理腳本程序,例如引擎。異步請(qǐng)求線程,也就是發(fā)出請(qǐng)求后,接收響應(yīng)檢測(cè)狀態(tài)變更等都是這個(gè)線程管理的。為了解決這個(gè)問(wèn)題,提出標(biāo)準(zhǔn),允許腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制,且不得操作。

本文主要參閱了以下兩篇文章,對(duì)JS的Event Loop運(yùn)行機(jī)制基礎(chǔ)知識(shí)進(jìn)行了整理。
從瀏覽器多進(jìn)程到JS單線程,JS運(yùn)行機(jī)制最全面的一次梳理
JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop

背景知識(shí) 進(jìn)程與線程

大家都知道JavaScript是單線程的,這就引申出一個(gè)問(wèn)題,進(jìn)程與線程是什么,他們的區(qū)別是什么?
先給出進(jìn)程和線程的定義:

進(jìn)程是cpu資源分配的最小單位(是能擁有資源和獨(dú)立運(yùn)行的最小單位)

線程是cpu調(diào)度的最小單位(線程是建立在進(jìn)程的基礎(chǔ)上的一次程序運(yùn)行單位,一個(gè)進(jìn)程中可以有多個(gè)線程)

用工廠和工人的例子來(lái)形象闡述:

- 進(jìn)程是一個(gè)工廠,工廠有它的獨(dú)立資源 -> 系統(tǒng)分配的內(nèi)存(獨(dú)立的一塊內(nèi)存)

- 工廠之間相互獨(dú)立 -> 進(jìn)程之間相互獨(dú)立

- 線程是工廠中的工人,多個(gè)工人協(xié)作完成任務(wù) -> 多個(gè)線程在進(jìn)程中協(xié)作完成任務(wù)

- 工廠內(nèi)有一個(gè)或多個(gè)工人 -> 一個(gè)進(jìn)程由一個(gè)或多個(gè)線程組成

- 工人之間共享工廠的資源 -> 同一進(jìn)程下的各個(gè)線程之間共享進(jìn)程的內(nèi)存空間(包括代碼段、數(shù)據(jù)集、堆等)

補(bǔ)充:

我們所說(shuō)的單線程和多線程,是指一個(gè)進(jìn)程內(nèi)是單一線程還是多線程。

進(jìn)程間的通信方式包括: 管道pipe、 命名管道FIFO、消息隊(duì)列MessageQueue、共享存儲(chǔ)SharedMemory、信號(hào)量Semaphore、套接字Socket、信號(hào)。

瀏覽器是多進(jìn)程的

關(guān)于瀏覽器進(jìn)程問(wèn)題可以簡(jiǎn)單基礎(chǔ)三點(diǎn):

瀏覽器是多進(jìn)程的。

瀏覽器之所以能夠運(yùn)行,是因?yàn)橄到y(tǒng)給它的進(jìn)程分配了資源(cpu、內(nèi)存)。

簡(jiǎn)單點(diǎn)理解,每打開(kāi)一個(gè)Tab頁(yè),就相當(dāng)于創(chuàng)建了一個(gè)獨(dú)立的瀏覽器進(jìn)程。

平時(shí) coding 接觸到最多的一個(gè)瀏覽器進(jìn)程是瀏覽器渲染進(jìn)程(瀏覽器內(nèi)核),它管理著頁(yè)面渲染。腳本執(zhí)行,事件處理等。要同時(shí)處理這么多事情,渲染進(jìn)程顯然是多線程的,它主要包括以下5個(gè)常駐線程:

GUI渲染線程,負(fù)責(zé)渲染瀏覽器界面,解析HTML,CSS,構(gòu)建DOM樹(shù)和RenderObject樹(shù),布局和繪制等。

JS引擎線程,也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序,(例如V8引擎)。

事件觸發(fā)線程,用來(lái)控制事件循環(huán)(可以理解為,JS引擎線程自己都忙不過(guò)來(lái),需要瀏覽器另開(kāi)線程協(xié)助)。

定時(shí)觸發(fā)器線程,瀏覽器定時(shí)計(jì)數(shù)器并不是由JavaScript引擎計(jì)數(shù)的,(因?yàn)镴avaScript引擎是單線程的, 如果處于阻塞線程狀態(tài)就會(huì)影響記計(jì)時(shí)的準(zhǔn)確),JS中常用的setIntervalsetTimeout就歸這個(gè)線程管理。

異步http請(qǐng)求線程,也就是ajax發(fā)出http請(qǐng)求后,接收響應(yīng)、檢測(cè)狀態(tài)變更等都是這個(gè)線程管理的。

我們常說(shuō)的JavaScript是單線程的,其實(shí)就是說(shuō)的JS引擎是單線程的,它僅僅是瀏覽器渲染進(jìn)程種的一個(gè)線程。為什么呢?因?yàn)镴avaScript的主要作用是與用戶互動(dòng),以及操作DOM,如果JavaScript有兩個(gè)線程,一個(gè)線程對(duì)一個(gè)DOM節(jié)點(diǎn)執(zhí)行 A 操作,另一個(gè)線程這個(gè)DOM節(jié)點(diǎn)執(zhí)行 B 操作,那么就會(huì)起沖突,所以JavaScript在前端的應(yīng)用就注定了它是單線程的。

然而JavaScript的單線程特性就注定我們不用它去完成密集的 cpu 運(yùn)算,因?yàn)槊芗?cpu 運(yùn)算耗時(shí)過(guò)長(zhǎng),阻塞頁(yè)面渲染。為了解決這個(gè)問(wèn)題,HTML5提出 Web Worker 標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制,且不得操作DOM

Event Loop

JavaScript 是單線程的帶來(lái)的問(wèn)題是:所有任務(wù)都必須同步執(zhí)行,問(wèn)題就出現(xiàn)了,很多 I/O 過(guò)程是非常耗時(shí)的(如http 請(qǐng)求數(shù)據(jù)),如果要等到 I/O 過(guò)程結(jié)束再執(zhí)行后續(xù)任務(wù),就會(huì)出現(xiàn)頁(yè)面的卡頓、cpu 的閑置。于是異步的任務(wù)就出現(xiàn)了,異步任務(wù)是指掛起處于等待中的任務(wù),繼續(xù)執(zhí)行同步任務(wù),等到結(jié)果返回再去繼續(xù)執(zhí)行被掛起的任務(wù)。于是,JavaScript 的任務(wù)可以分為同步任務(wù)和異步任務(wù)。下面就引出 Event Loop 機(jī)制:

所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧

主線程之外,事件觸發(fā)線程管理著一個(gè)任務(wù)隊(duì)列,只要異步任務(wù)有了運(yùn)行結(jié)果,就在任務(wù)隊(duì)列之中放置一個(gè)事件。

一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢(此時(shí)JS引擎空閑),系統(tǒng)就會(huì)讀取任務(wù)隊(duì)列,將可運(yùn)行的異步任務(wù)添加到執(zhí)行棧中,開(kāi)始執(zhí)行。

如上圖所示,執(zhí)行棧中的代碼會(huì)調(diào)用一個(gè)異步的API,它們會(huì)在任務(wù)隊(duì)列中添加各種事件(或者說(shuō)回調(diào)函數(shù)),另外用戶的操作如click、mousedown等都會(huì)在任務(wù)隊(duì)列中添加事件。只要執(zhí)行棧中的代碼執(zhí)行完畢,主線程就會(huì)去讀取任務(wù)隊(duì)列,將可執(zhí)行的回調(diào)函數(shù)放到執(zhí)行棧中執(zhí)行。

總結(jié)一下:

執(zhí)行棧執(zhí)行完畢 -> 主線程讀取任務(wù)隊(duì)列,并執(zhí)行回調(diào)函數(shù) -> 執(zhí)行棧執(zhí)行完畢 -> 主線程讀取任務(wù)隊(duì)列,并執(zhí)行回調(diào)函數(shù) ...

這個(gè)過(guò)程一直循環(huán)下去,所以就叫事件循環(huán)(Event Loop)。

setTimeout 和 setInterval

前面提到了瀏覽器的定時(shí)觸發(fā)器線程,它的主要作用就是計(jì)時(shí),setTimeoutsetInterval 就由它來(lái)控制,原理就是到達(dá)設(shè)置時(shí)間后,往任務(wù)隊(duì)列中添加這兩個(gè)函數(shù)中指定的回調(diào)函數(shù)。

setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。但是需要注意的是,實(shí)際是計(jì)時(shí)結(jié)束后定時(shí)觸發(fā)器線程才會(huì)將回調(diào)函數(shù)放到任務(wù)隊(duì)列中去,此時(shí)任務(wù)隊(duì)列中這個(gè)回調(diào)之前可能已經(jīng)有一些事件待處理,并且一定要執(zhí)行棧的任務(wù)執(zhí)行完后才會(huì)開(kāi)始執(zhí)行任務(wù)隊(duì)列中的任務(wù),所以 setTimeout() 中回調(diào)開(kāi)始執(zhí)行的時(shí)間是:執(zhí)行棧執(zhí)行時(shí)間 + 任務(wù)隊(duì)列前方回調(diào)執(zhí)行時(shí)間 + 延遲時(shí)間

setInterval() 方法可按照指定的時(shí)間間隔來(lái)周期性調(diào)用函數(shù)或計(jì)算表達(dá)式。它的問(wèn)題在于:每次都精確的隔一段時(shí)間將一個(gè)回調(diào)放到任務(wù)隊(duì)列中,并沒(méi)有考慮到內(nèi)部回調(diào)函數(shù)執(zhí)行所需時(shí)間,這就會(huì)導(dǎo)致兩種問(wèn)題:

回調(diào)函數(shù)執(zhí)行需要時(shí)間,兩個(gè)函數(shù)執(zhí)行的時(shí)間間隔會(huì)小于設(shè)定值;

如果回調(diào)函數(shù)執(zhí)行時(shí)間大于設(shè)定間隔,就會(huì)出現(xiàn)上一個(gè)加入任務(wù)隊(duì)列中的回調(diào)還沒(méi)執(zhí)行完,下一個(gè)回調(diào)就被加入任務(wù)隊(duì)列了,就會(huì)出現(xiàn)累計(jì)效應(yīng),即后面的回調(diào)會(huì)連續(xù)執(zhí)行。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96459.html

相關(guān)文章

  • event loop規(guī)范探究javaScript異步及瀏覽器更新渲染時(shí)機(jī)

    摘要:規(guī)范中定義了瀏覽器何時(shí)進(jìn)行渲染更新,了解它有助于性能優(yōu)化。結(jié)合一些資料,對(duì)上邊規(guī)范給出一些理解有誤請(qǐng)指正每個(gè)線程都有自己的。列為,列為,列為。我們都知道是單線程,渲染計(jì)算和腳本運(yùn)行共用同一線程網(wǎng)絡(luò)請(qǐng)求會(huì)有其他線程,導(dǎo)致腳本運(yùn)行會(huì)阻塞渲染。 本文轉(zhuǎn)自blog 轉(zhuǎn)載請(qǐng)注明出處 異步的思考 event loops隱藏得比較深,很多人對(duì)它很陌生。但提起異步,相信每個(gè)人都知道。異步背后的靠山就是...

    13651657101 評(píng)論0 收藏0
  • event loop 與 vue

    摘要:但是導(dǎo)致了很明顯的性能問(wèn)題。上述兩個(gè)例子其實(shí)是在這個(gè)中找到的,第一個(gè)使用的版本是,這個(gè)版本的實(shí)現(xiàn)是采用了,而后因?yàn)榈睦锏挠?,于是尤雨溪更改了?shí)現(xiàn),換成了,也就是后一個(gè)所使用的。后來(lái)尤雨溪了解到是將回調(diào)放入的隊(duì)列。 結(jié)論 對(duì)于event loop 可以抽象成一段簡(jiǎn)單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...

    springDevBird 評(píng)論0 收藏0
  • event loop 與 vue

    摘要:但是導(dǎo)致了很明顯的性能問(wèn)題。上述兩個(gè)例子其實(shí)是在這個(gè)中找到的,第一個(gè)使用的版本是,這個(gè)版本的實(shí)現(xiàn)是采用了,而后因?yàn)榈睦锏挠?,于是尤雨溪更改了?shí)現(xiàn),換成了,也就是后一個(gè)所使用的。后來(lái)尤雨溪了解到是將回調(diào)放入的隊(duì)列。 結(jié)論 對(duì)于event loop 可以抽象成一段簡(jiǎn)單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...

    Barry_Ng 評(píng)論0 收藏0
  • JavaScript 事件循環(huán)(譯文JavaScript Event Loop

    摘要:事件循環(huán)了解了在引擎中是如何工作了之后,來(lái)看下如何使用異步回調(diào)函數(shù)來(lái)避免代碼。從回調(diào)函數(shù)被放入后秒鐘,把移到中。由于事件循環(huán)持續(xù)地監(jiān)測(cè)調(diào)用棧是否已空,此時(shí)它一注意到調(diào)用??樟耍驼{(diào)用并創(chuàng)建一個(gè)新的調(diào)用棧。 聽(tīng)多了JavaScript單線程,異步,V8,便會(huì)很想去知道JavaScript是如何利用單線程來(lái)實(shí)現(xiàn)所謂的異步的。我參考了一些文章,了解到一個(gè)很重要的詞匯:事件循環(huán)(Event L...

    K_B_Z 評(píng)論0 收藏0
  • Javascript 運(yùn)行機(jī)制詳解,Event Loop

    摘要:主線程在任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷地,所以這種運(yùn)行機(jī)制叫做事件循環(huán)是在執(zhí)行棧同步代碼結(jié)束之后,下一次任務(wù)隊(duì)列執(zhí)行之前。 單線程 javascript為什么是單線程語(yǔ)言,原因在于如果是多線程,當(dāng)一個(gè)線程對(duì)DOM節(jié)點(diǎn)做添加內(nèi)容操作的時(shí)候,另一個(gè)線程要?jiǎng)h除這個(gè)DOM節(jié)點(diǎn),這個(gè)時(shí)候,瀏覽器應(yīng)該怎么選擇,這就造成了混亂,為了解決這類問(wèn)題,在一開(kāi)始的時(shí)候,javascript就采用單線...

    Jingbin_ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<