成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Event Loop - JS執(zhí)行機(jī)制

muddyway / 2877人閱讀

摘要:心塞塞根據(jù)規(guī)范,事件循環(huán)是通過任務(wù)隊(duì)列的機(jī)制來進(jìn)行協(xié)調(diào)的。等便是任務(wù)源,而進(jìn)入任務(wù)隊(duì)列的是他們指定的具體執(zhí)行任務(wù)回調(diào)函數(shù)。然后當(dāng)前本輪的結(jié)束,主線程可以繼續(xù)取下一個執(zhí)行。

依然是:經(jīng)濟(jì)基礎(chǔ)決定上層建筑。

說明

首先,旨在搞清常用的同步異步執(zhí)行機(jī)制

其次,暫時(shí)不討論node.js的Event Loop執(zhí)行機(jī)制,以下關(guān)于瀏覽器的Event Loop執(zhí)行機(jī)制

最后,借鑒了很多前輩的研究文章,非常感謝,此文主要是梳理所學(xué),還請保持質(zhì)疑以追求正確的知識

要點(diǎn)

基本概念

同步異步操作

Event Loop

基本概念

先解釋現(xiàn)代js引擎幾個概念。


stack(棧):這里放著js正在執(zhí)行的任務(wù)。理解事件循環(huán)一(淺析)一文有對 stack 的 example 解釋。

heap(堆):一個用來表示內(nèi)存中一大片非結(jié)構(gòu)化區(qū)域的名字,對象都被分配在這。

queue(隊(duì)列):一個 js runtime 包含了一個任務(wù)隊(duì)列,該隊(duì)列是由一系列待處理的任務(wù)組成。而每個任務(wù)都有相對應(yīng)的函數(shù)。當(dāng)棧為空時(shí),就會從任務(wù)隊(duì)列中取出一個任務(wù),并處理之。當(dāng)該任務(wù)處理完畢后,棧就會再次為空。(queue的特點(diǎn)是先進(jìn)先出(FIFO))。

為了方便描述與理解,作出以下約定:

stack 棧為主線程

queue 隊(duì)列為任務(wù)隊(duì)列(等待調(diào)度到主線程執(zhí)行)

同步異步

js 是一門單線程語言。 js 引擎有一個主線程(main thread)用來解釋和執(zhí)行 js 程序,實(shí)際上還存在其他的線程。例如:處理AJAX請求的線程、處理DOM事件的線程、定時(shí)器線程、讀寫文件的線程(例如在node.js中)等等。這些線程可能存在于 js 引擎之內(nèi),也可能存在于 js 引擎之外,在此我們不做區(qū)分。不妨叫它們工作線程。但是前輩們頗有一種小本本記好的說法,那就是,要相信 js 單線程的本質(zhì),其他一切看似多線程,都是紙老虎。哈哈哈哈哈哈哈哈哈哈哈哈哈......

任務(wù)分為同步任務(wù)(synchronous)和異步任務(wù)(asynchronous),如果所有任務(wù)都由主線程來處理,會出現(xiàn)主線程被阻塞而使得頁面“假死”。為了主線程不被阻塞,異步任務(wù)(如:AJAX異步請求,定時(shí)器等)就會交給工作線程來處理,異步任務(wù)完成后將異步回調(diào)函數(shù)注冊進(jìn)任務(wù)隊(duì)列,等待主線程空閑時(shí)調(diào)用。流程如圖:


// example
console.log("example-start")

setTimeout(() => {
  console.log("setTimeout-0")
}, 0)

console.log("example-end")

/* chrome result
 * 
    example-start
    example-end
    setTimeout-0
 *
 */

上面一個簡單的小 js 片段的執(zhí)行過程:

主線程開始同步任務(wù)執(zhí)行,執(zhí)行console.log("example-start")

然后接下來,主線程遇見一個異步操作setTimeout,將改異步任務(wù)交給工作線程處理,異步任務(wù)完成之后,將回調(diào)函數(shù)注冊進(jìn)任務(wù)隊(duì)列,等待被調(diào)用

繼續(xù)同步任務(wù)處理,執(zhí)行console.log("example-end")

主線程空閑,調(diào)用任務(wù)隊(duì)列中等待執(zhí)行的回調(diào)函數(shù),執(zhí)行console.log("setTimeout-0")

最后借用Philip Roberts的生動形象的一張圖,callback queue可以簡單理解為任務(wù)隊(duì)列,詳細(xì)的下面會講。


Event Loop

然而Event Loop并沒有上面圖中描述那么簡單。心塞塞 : (

根據(jù)規(guī)范,事件循環(huán)是通過任務(wù)隊(duì)列的機(jī)制來進(jìn)行協(xié)調(diào)的。一個 Event Loop 中,可以有一個或者多個任務(wù)隊(duì)列(task queue),一個任務(wù)隊(duì)列便是一系列有序任務(wù)(task)的集合;每個任務(wù)都有一個任務(wù)源(task source),源自同一個任務(wù)源的 task 必須放到同一個任務(wù)隊(duì)列,從不同源來的則被添加到不同隊(duì)列。

setTimeout/Promise 等API便是任務(wù)源,而進(jìn)入任務(wù)隊(duì)列的是他們指定的具體執(zhí)行任務(wù)(回調(diào)函數(shù))。來自不同任務(wù)源的任務(wù)會進(jìn)入到不同的任務(wù)隊(duì)列。其中setTimeout與setInterval是同源的。

仔細(xì)查閱規(guī)范可知,異步任務(wù)可分為 task(部分文章也稱為 macro-task) 和 micro-task 兩類,不同的API注冊的異步任務(wù)會依次進(jìn)入自身對應(yīng)的隊(duì)列中,然后等待 Event Loop 將它們依次壓入執(zhí)行棧中執(zhí)行。

task主要包含:script(整體代碼)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(node.js 環(huán)境)

micro-task主要包含:Promise.then、MutaionObserver、MessageChannel、process.nextTick(node.js 環(huán)境)

在事件循環(huán)中,每進(jìn)行一次循環(huán)操作稱為 tick,每一次 tick 的任務(wù)處理模型是比較復(fù)雜的,但關(guān)鍵步驟如下:

在此次 tick 中選擇最先進(jìn)入隊(duì)列的任務(wù)(oldest task),如果有則執(zhí)行(一次)

檢查是否存在 micro-task,如果存在則不停地執(zhí)行,直至清空 micro-task queue

更新 render

主線程重復(fù)執(zhí)行上述步驟

一個事件循環(huán)(Event Loop)中,主線程從任務(wù)隊(duì)列中取出一個任務(wù) task 執(zhí)行時(shí),而這個正在執(zhí)行的任務(wù)就是從 task queue(部分文章也稱為 macro-task queue)中來的。當(dāng)這個 task 執(zhí)行結(jié)束后,js 會將 micro-task queue中所有 micro-task 都在同一個 Event Loop 中執(zhí)行,當(dāng)這些 micro-task 執(zhí)行結(jié)束后還能繼續(xù)添加 micro-task 一直到整個 micro-task 隊(duì)列執(zhí)行結(jié)束。然后當(dāng)前本輪的 Event Loop 結(jié)束,主線程可以繼續(xù)取下一個 task 執(zhí)行。所以更詳細(xì)的 Event Loop 的流程圖如下:

// example
console.log("example-start")

setTimeout(() => {
  console.log("setTimeout-0") // setTimeout-1
}, 0)

new Promise((resolve, reject) => {
  console.log("promise-1")
  resolve("promise-2")
  Promise.resolve().then(() => console.log("promise-3")) // then-1
}).then((response) => { // then-2
  console.log(response)
  setTimeout(() => {
    console.log("setTimeout-10") // setTimeout-2
  }, 10)
})

console.log("example-end")

/* chrome result
 * 
    example-start
    promise-1
    example-end
    promise-3
    promise-2
    setTimeout-0
    setTimeout-10
 *
 */

上面一個簡單的 js 片段的執(zhí)行過程:

第一輪事件循環(huán):

第二輪事件循環(huán):

第三輪事件循環(huán):

如果上文理解有誤或者有疑惑,歡迎交流。

參考

Philip Roberts: Help, I’m stuck in an event-loop.

JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop

關(guān)于JavaScript單線程的一些事

從一道題淺說 JavaScript 的事件循環(huán)

Event Loop的規(guī)范和實(shí)現(xiàn)

這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制

好記性不如爛筆頭。

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/95264.html

相關(guān)文章

  • 10分鐘理解JS引擎的執(zhí)行機(jī)制

    摘要:深入理解引擎的執(zhí)行機(jī)制靈魂三問為什么是單線程的為什么需要異步單線程又是如何實(shí)現(xiàn)異步的呢中的中的說說首先請牢記點(diǎn)是單線程語言的是的執(zhí)行機(jī)制。 深入理解JS引擎的執(zhí)行機(jī)制 1.靈魂三問 : JS為什么是單線程的? 為什么需要異步? 單線程又是如何實(shí)現(xiàn)異步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.說說setTimeout 首先,請牢記2...

    zzbo 評論0 收藏0
  • JavaScript執(zhí)行機(jī)制、事件循環(huán)

    摘要:曾經(jīng)的理解首先,是單線程語言,也就意味著同一個時(shí)間只能做一件事,那么為什么不是多線程呢這樣還能提高效率啊假定同時(shí)有兩個線程,一個線程在某個節(jié)點(diǎn)上編輯了內(nèi)容,而另一個線程刪除了這個節(jié)點(diǎn),這時(shí)瀏覽器就很懵逼了,到底以執(zhí)行哪個操作呢所以,設(shè)計(jì)者把 Event Loop曾經(jīng)的理解 首先,JS是單線程語言,也就意味著同一個時(shí)間只能做一件事,那么 為什么JavaScript不是多線程呢?這樣還能提...

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

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

    Jingbin_ 評論0 收藏0
  • 深入理解js引擎的執(zhí)行機(jī)制

    摘要:深入理解引擎的執(zhí)行機(jī)制最近在反省,很多知識都是只會用,不理解底層的知識。在閱讀之前,請先記住兩點(diǎn)是單線程語言的是的執(zhí)行機(jī)制。所以,是存在異步執(zhí)行的,比如單線程是怎么實(shí)現(xiàn)異步的場景描述通過事件循環(huán),所以說,理解了機(jī)制,也就理解了的執(zhí)行機(jī)制啦。 深入理解js引擎的執(zhí)行機(jī)制 最近在反省,很多知識都是只會用,不理解底層的知識。所以在開發(fā)過程中遇到一些奇怪的比較難解決的bug,在思考的時(shí)候就會收...

    feng409 評論0 收藏0
  • 理解JS中的Event Loop機(jī)制

    摘要:前言前幾天在理解的事件環(huán)機(jī)制中引發(fā)了我對瀏覽器里的好奇。接下來理解瀏覽器中的,先看一張圖堆和棧堆是用戶主動請求而劃分出來的內(nèi)存區(qū)域,比如你,就是將一個對象存入堆中,可以理解為存對象。廢話不多說,直接上圖個人理解。參考資料運(yùn)行機(jī)制詳解再談 前言 前幾天在理解node的事件環(huán)機(jī)制中引發(fā)了我對瀏覽器里Event Loop的好奇。我們都知道javascript是單線程的,任務(wù)是需要一個一個按順...

    MASAILA 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<