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

資訊專欄INFORMATION COLUMN

Js 的事件循環(huán)(Event Loop)機制以及實例講解

Anshiii / 1262人閱讀

摘要:主線程要明確的一點是,主線程跟執(zhí)行棧是不同概念,主線程規(guī)定現(xiàn)在執(zhí)行執(zhí)行棧中的哪個事件。主線程循環(huán)即主線程會不停的從執(zhí)行棧中讀取事件,會執(zhí)行完所有棧中的同步代碼。以上參考資料詳解中的事件循環(huán)機制中的事件循環(huán)運行機制詳解再談

前言

大家都知道js是單線程的腳本語言,在同一時間,只能做同一件事,為了協(xié)調(diào)事件、用戶交互、腳本、UI渲染和網(wǎng)絡處理等行為,防止主線程阻塞,Event Loop方案應運而生...

個人博客了解一下:obkoro1.com
為什么js是單線程?

js作為主要運行在瀏覽器的腳本語言,js主要用途之一是操作DOM。

在js高程中舉過一個栗子,如果js同時有兩個線程,同時對同一個dom進行操作,這時瀏覽器應該聽哪個線程的,如何判斷優(yōu)先級?

為了避免這種問題,js必須是一門單線程語言,并且在未來這個特點也不會改變。

執(zhí)行棧與任務隊列

因為js是單線程語言,當遇到異步任務(如ajax操作等)時,不可能一直等待異步完成,再繼續(xù)往下執(zhí)行,在這期間瀏覽器是空閑狀態(tài),顯而易見這會導致巨大的資源浪費。

執(zhí)行棧

當執(zhí)行某個函數(shù)、用戶點擊一次鼠標,Ajax完成,一個圖片加載完成等事件發(fā)生時,只要指定過回調(diào)函數(shù),這些事件發(fā)生時就會進入執(zhí)行棧隊列中,等待主線程讀取,遵循先進先出原則。

主線程

要明確的一點是,主線程跟執(zhí)行棧是不同概念,主線程規(guī)定現(xiàn)在執(zhí)行執(zhí)行棧中的哪個事件。

主線程循環(huán):即主線程會不停的從執(zhí)行棧中讀取事件,會執(zhí)行完所有棧中的同步代碼。

當遇到一個異步事件后,并不會一直等待異步事件返回結(jié)果,而是會將這個事件掛在與執(zhí)行棧不同的隊列中,我們稱之為任務隊列(Task Queue)。

當主線程將執(zhí)行棧中所有的代碼執(zhí)行完之后,主線程將會去查看任務隊列是否有任務。如果有,那么主線程會依次執(zhí)行那些任務隊列中的回調(diào)函數(shù)。

不太理解的話,可以運行一下下面的代碼,或者點擊一下這個demo

結(jié)果是當a、b、c函數(shù)都執(zhí)行完成之后,三個setTimeout才會依次執(zhí)行。

let a = () => {
  setTimeout(() => {
    console.log("任務隊列函數(shù)1")
  }, 0)
  for (let i = 0; i < 5000; i++) {
    console.log("a的for循環(huán)")
  }
  console.log("a事件執(zhí)行完")
}
let b = () => {
  setTimeout(() => {
    console.log("任務隊列函數(shù)2")
  }, 0)
  for (let i = 0; i < 5000; i++) {
    console.log("b的for循環(huán)")
  }
  console.log("b事件執(zhí)行完")
}
let c = () => {
  setTimeout(() => {
    console.log("任務隊列函數(shù)3")
  }, 0)
  for (let i = 0; i < 5000; i++) {
    console.log("c的for循環(huán)")
  }
  console.log("c事件執(zhí)行完")
}
a();
b();
c();
// 當a、b、c函數(shù)都執(zhí)行完成之后,三個setTimeout才會依次執(zhí)行
js 異步執(zhí)行的運行機制。

所有任務都在主線程上執(zhí)行,形成一個執(zhí)行棧。

主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結(jié)果,就在"任務隊列"之中放置一個事件。

一旦"執(zhí)行棧"中的所有同步任務執(zhí)行完畢,系統(tǒng)就會讀取"任務隊列"。那些對應的異步任務,結(jié)束等待狀態(tài),進入執(zhí)行棧并開始執(zhí)行。

主線程不斷重復上面的第三步。

宏任務與微任務:

異步任務分為 宏任務(macrotask) 與 微任務 (microtask),不同的API注冊的任務會依次進入自身對應的隊列中,然后等待 Event Loop 將它們依次壓入執(zhí)行棧中執(zhí)行。

宏任務(macrotask):

script(整體代碼)、setTimeout、setInterval、UI 渲染、 I/O、postMessage、 MessageChannel、setImmediate(Node.js 環(huán)境)

微任務(microtask):

Promise、 MutaionObserver、process.nextTick(Node.js環(huán)境)

Event Loop(事件循環(huán)):

Event Loop(事件循環(huán))中,每一次循環(huán)稱為 tick, 每一次tick的任務如下:

執(zhí)行棧選擇最先進入隊列的宏任務(通常是script整體代碼),如果有則執(zhí)行

檢查是否存在 Microtask,如果存在則不停的執(zhí)行,直至清空 microtask 隊列

更新render(每一次事件循環(huán),瀏覽器都可能會去更新渲染)

重復以上步驟

宏任務 > 所有微任務 > 宏任務,如下圖所示:

從上圖我們可以看出:

將所有任務看成兩個隊列:執(zhí)行隊列與事件隊列。

執(zhí)行隊列是同步的,事件隊列是異步的,宏任務放入事件列表,微任務放入執(zhí)行隊列之后,事件隊列之前。

當執(zhí)行完同步代碼之后,就會執(zhí)行位于執(zhí)行列表之后的微任務,然后再執(zhí)行事件列表中的宏任務

上面提到的demo結(jié)果可以這么理解:先執(zhí)行script宏任務,執(zhí)行完了之后,再執(zhí)行其他兩個定時器宏任務。

面試題實踐

下面這個題,很多人都應該看過/遇到過,重新來看會不會覺得清晰很多:

    // 執(zhí)行順序問題,考察頻率挺高的,先自己想答案**
    setTimeout(function () {
        console.log(1);
    });
    new Promise(function(resolve,reject){
        console.log(2)
        resolve(3)
    }).then(function(val){
        console.log(val);
    })
    console.log(4);

根據(jù)本文的解析,我們可以得到:

先執(zhí)行script同步代碼

先執(zhí)行new Promise中的console.log(2),then后面的不執(zhí)行屬于微任務
然后執(zhí)行console.log(4)

執(zhí)行完script宏任務后,執(zhí)行微任務,console.log(3),沒有其他微任務了。

執(zhí)行另一個宏任務,定時器,console.log(1)。

根據(jù)本文的內(nèi)容,可以很輕松,且有理有據(jù)的猜出寫出正確答案:2,4,3,1.

結(jié)語

類似上文的面試題還有很多,實則都大同小異,只要掌握了事件循環(huán)的機制,這些問題都會變得很簡單。

文章如有不正確的地方歡迎各位路過的大佬鞭策!希望大家看完可以有所收獲,喜歡的話,趕緊點波訂閱關注/喜歡。

看完的朋友可以點個喜歡/關注,您的支持是對我最大的鼓勵。

個人blog and 掘金個人主頁,如需轉(zhuǎn)載,請放上原文鏈接并署名。碼字不易,感謝支持!

如果喜歡本文的話,歡迎關注我的訂閱號,漫漫技術路,期待未來共同學習成長。

以上2018.6.16

參考資料:

詳解JavaScript中的Event Loop(事件循環(huán))機制

JavaScript中的事件循環(huán) Event Loop

JavaScript 運行機制詳解:再談Event Loop

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

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

相關文章

  • JS忍者秘籍中定時器機制詳解

    摘要:設置和清除定時器直接引用忍者秘籍中的圖片注意定時器的時間間隔設為,也會有幾毫秒的延遲。以上參考資料忍者秘籍第章馴服線程和定時器 showImg(https://segmentfault.com/img/remote/1460000015353524?w=1024&h=681); 前言 前段時間剛看完《JS忍者秘籍》,雖說是15年出版的,有些東西是過時了,但像對原型鏈、閉包、正則、定時器...

    keelii 評論0 收藏0
  • 由setTimeout深入JavaScript執(zhí)行環(huán)境異步機制

    摘要:圖片轉(zhuǎn)引自的演講和兩個定時器中回調(diào)的執(zhí)行邏輯便是典型的機制。異步編程關于異步編程我的理解是,在執(zhí)行環(huán)境所提供的異步機制之上,在應用編碼層面上實現(xiàn)整體流程控制的異步風格。 問題背景 在一次開發(fā)任務中,需要實現(xiàn)如下一個餅狀圖動畫,基于canvas進行繪圖,但由于對于JS運行環(huán)境中異步機制的不了解,所以遇到了一個棘手的問題,始終無法解決,之后在與同事交流之后才恍然大悟。問題的根節(jié)在于經(jīng)典的J...

    codeGoogle 評論0 收藏0
  • 瀏覽器與NodeJSEventLoop異同,以及部分機制

    摘要:瀏覽器與的異同,以及部分機制有人對部分迷惑,本身構(gòu)造函數(shù)是同步的,是異步。瀏覽器的的已全部分析完成,過程中引用阮一峰博客,知乎,部分文章內(nèi)容,侵刪。 瀏覽器與NodeJS的EventLoop異同,以及部分機制 PS:有人對promise部分迷惑,Promise本身構(gòu)造函數(shù)是同步的,.then是異步。---- 2018/7/6 22:35修改 javascript 是一門單線程的腳本...

    jubincn 評論0 收藏0
  • 事件循環(huán)機制event loop

    摘要:了解事件循環(huán)機制有助于理解的執(zhí)行過程,同時這也是面試常見題。那么這個回調(diào)函數(shù)將在何時由誰執(zhí)行呢已知是瀏覽器環(huán)境提供的,因此瀏覽器將對它進行處理,瀏覽器會在本次事件完成,即計時結(jié)束后,將回調(diào)函數(shù)加入循環(huán)隊列中,然后等待被加入執(zhí)行棧執(zhí)行。 如果有人問JavaScript是什么,也許你會說它是一個單線程、非阻塞、異步、解釋型的腳本語言。那么作為一個單線程語言,它是怎么實現(xiàn)非阻塞、異步的?這就...

    tain335 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<