談?wù)?Event Loop(事件循環(huán))機(jī)制

在講 Event Loop (事件循環(huán))之前猎拨,我們來了解點(diǎn) node 的東西,來幫助我們更加明白事件循環(huán)是干什么的

Node 是什么

Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境凹联,Node 不是一門語言,是讓 js 運(yùn)行在后端的,運(yùn)行時不包括 js 全集未辆,因?yàn)樵诜?wù)端中不包含 DOM 和 BOM,Node 也提供了一些新的模塊锯玛,比如 http咐柜,fs等模塊。

Node 解決了什么

Node 的首要目標(biāo)是提供一種簡單的攘残,用于創(chuàng)建高性能服務(wù)器的開發(fā)工具
Web 服務(wù)器的瓶頸在于并發(fā)的用戶量拙友,對比 Java 和 Php 的實(shí)現(xiàn)方式

Node在處理高并發(fā),I/O 密集場景有明顯的性能優(yōu)勢
  • 高并發(fā),是指在同一時間并發(fā)訪問服務(wù)器
  • I/O 密集指的是文件操作歼郭、網(wǎng)絡(luò)操作遗契、數(shù)據(jù)庫,相對的有 CPU 密集,CPU 密集指的是邏輯處理運(yùn)算、壓縮病曾、解壓牍蜂、加密、解密

Web 主要場景就是接收客戶端的請求讀取靜態(tài)資源和渲染界面,所以 Node 非常適合 Web 應(yīng)用的開發(fā)泰涂。

進(jìn)程與線程

進(jìn)程是操作系統(tǒng)分配資源和調(diào)度任務(wù)的基本單位鲫竞,線程是建立在進(jìn)程上的一次程序運(yùn)行單位,一個進(jìn)程上可以有多個線程逼蒙。

  1. 瀏覽器線程
    • 用戶界面-包括地址欄从绘、前進(jìn)/后退按鈕、書簽菜單等
    • 瀏覽器引擎-在用戶界面和呈現(xiàn)引擎之間傳送指令(瀏覽器的主進(jìn)程)
    • 渲染引擎是牢,也被稱為瀏覽器內(nèi)核(瀏覽器渲染進(jìn)程)
    • 一個插件對應(yīng)一個進(jìn)程(第三方插件進(jìn)程)
    • GPU提高網(wǎng)頁瀏覽的體驗(yàn)( GPU 進(jìn)程)
  2. 瀏覽器渲染引擎
    • 渲染引擎內(nèi)部是多線程的顶考,內(nèi)部包含 ui 線程和 js 線程
    • js 線程 ui 線程 這兩個線程互斥的,目的就是為了保證不產(chǎn)生沖突妖泄。
    • ui 線程會把更改的放到隊(duì)列中驹沿,當(dāng) js 線程空閑下來的時候,ui 線程在繼續(xù)渲染
  3. js 單線程
    • js 是單線程蹈胡,為什么呢渊季?如果多個線程同時操作 DOM 朋蔫,哪頁面不會很混亂?這里所謂的單線程指的是主線程是單線程的,所以在 Node 中主線程依舊是單線程的却汉。
  4. webworker 多線程
    • 它和 js 主線程不是平級的驯妄,主線程可以控制 webworker,但是 webworker不能操作 DOM合砂,不能獲取 document青扔,window
  5. 其他線程
    • 瀏覽器事件觸發(fā)線程(用來控制事件循環(huán),存放 setTimeout、瀏覽器事件翩伪、ajax 的回調(diào)函數(shù))
    • 定時觸發(fā)器線程(setTimeout 定時器所在線程)
    • 異步 HTTP 請求線程(ajax 請求線程)

單線程特點(diǎn)是節(jié)約了內(nèi)存,并且不需要在切換執(zhí)行上下文微猖。而且單線程不需要管鎖的問題,所謂 鎖,在 java 里才有鎖的概念缘屹,所以我們不用細(xì)研究

瀏覽器中的 Event Loop

2.jpg
  • 同步任務(wù)都在主線程上執(zhí)行凛剥,形成一個執(zhí)行棧
  • 主線程之外,還存在一個任務(wù)隊(duì)列轻姿。只要異步任務(wù)有了運(yùn)行結(jié)果犁珠,就在任務(wù)隊(duì)列之中放置一個事件。
  • 一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢互亮,系統(tǒng)就會讀取任務(wù)隊(duì)列,將隊(duì)列中的事件放到執(zhí)行棧中依次執(zhí)行
  • 主線程從任務(wù)隊(duì)列中讀取事件犁享,這個過程是循環(huán)不斷的

整個的這種運(yùn)行機(jī)制又稱為 Event Loop (事件循環(huán))

node 中的 Event Loop

如圖(圖片是借鑒的):


3.jpg

* 我們寫的代碼會交給 V8 引擎去進(jìn)行處理
* 代碼中可能會調(diào)用 nodeApi,node 會交給 LIBUV 庫處理
* LIBUV 通過阻塞 i/o 和多線程實(shí)現(xiàn)了異步 io
* 通過事件驅(qū)動的方式,將結(jié)果放到事件隊(duì)列中,最終交給我們的應(yīng)用豹休。

同步炊昆,異步 阻塞和非阻塞

  • 阻塞和非阻塞指的是調(diào)用者的狀態(tài),關(guān)注的是程序在等待調(diào)用結(jié)果時的狀態(tài)
  • 同步和異步指的是被調(diào)用者是如何通知的慕爬,關(guān)注的是消息通知機(jī)制

宏任務(wù)和微任務(wù)

  • macro-task(宏任務(wù)):
    • setTimeout, setInterval, setImmediate, I/O
  • micro-task(微任務(wù)):
    • process.nextTick,
    • 原生 Promise (有些實(shí)現(xiàn)的promise 將 then 方法放到了宏任務(wù)中,瀏覽器默認(rèn)放到了微任務(wù)),
    • Object.observe (已廢棄),
    • MutationObserver(不兼容屏积,已廢棄)
    • MessageChannel(vue中 nextClick 實(shí)現(xiàn)原理)

同步代碼先執(zhí)行医窿,執(zhí)行是在棧中執(zhí)行的,微任務(wù)大于宏任務(wù)炊林,微任務(wù)會先執(zhí)行(棧)姥卢,宏任務(wù)后執(zhí)行(隊(duì)列)

講到這里,敲幾行代碼來總結(jié)下我們上面講到的知識點(diǎn)把

《1》宏任務(wù)渣聚,微任務(wù)在瀏覽器和 node 環(huán)境執(zhí)行順序不同

// 這個列子里面独榴,包含了宏任務(wù),微任務(wù)奕枝,分別看看瀏覽器和node 打印的結(jié)果
console.log(1)
// 棧
setTimeout(function(){
    console.log(2)
    // 微任務(wù)
    Promise.resolve(100).then(function(){
        console.log('promise')
    })
})
// 棧
let promise = new Promise(function(resolve, reject){
    console.log(7)
    resolve(100)
}).then(function(data){
    // 微任務(wù)
    console.log(data)
})
// 棧
setTimeout(function(){
    console.log(3)
})
console.log(5)
// 瀏覽器結(jié)果:1 7 5 100 2 promise 3
// node 結(jié)果:  1 7 5 100 2 3 promise

瀏覽器和 node 環(huán)境執(zhí)行順序不同棺榔,瀏覽器是先把一個棧以及棧中的微任務(wù)走完,才會走下一個棧隘道。node 環(huán)境里面是把所以棧走完症歇,才走微任務(wù)

《2》setTimeout setImmediate 都是宏任務(wù)郎笆,誰優(yōu)先執(zhí)行呢?

setTimeout(function(){
    console.log('timeout')
})
setImmediate(function(){
    console.log('setImmediate')
})
// 結(jié)果打油睢:timeout setImmediate

setTimeout setImmediate 這兩個取決于 node 的執(zhí)行時間

《3》nextTick 和 then 都屬于微任務(wù)宛蚓,誰優(yōu)先執(zhí)行呢?

process.nextTick(function(){
    console.log('nextTick')
})
Promise.resolve().then(function(){
    console.log('then')
})
// 結(jié)果打由杷:nextTick then

// 再加一個宏任務(wù)呢
setImmediate(function(){
    console.log('setImmediate')
})
// 結(jié)果打悠嗬簟:nextTick  then  setImmediate

nextTick 會比 其他微任務(wù)、宏任務(wù)執(zhí)行快

《4》i/o 文件操作(宏任務(wù))闰蛔,搭配微任務(wù)痕钢,誰優(yōu)先執(zhí)行呢?

let fs = require('fs');
fs.readFile('./1/log',function(){
    console.log('fs')
})
process.nextTick(function(){
    console.log('text')
})
// 結(jié)果打映ぁ:text  fs

i/o 文件操作(宏任務(wù)), 如果有微任務(wù)盖喷,先執(zhí)行微任務(wù),在執(zhí)行文件讀取

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末难咕,一起剝皮案震驚了整個濱河市课梳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌余佃,老刑警劉巖暮刃,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異爆土,居然都是意外死亡椭懊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門步势,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氧猬,“玉大人,你說我怎么就攤上這事坏瘩≈迅В” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵倔矾,是天一觀的道長妄均。 經(jīng)常有香客問我,道長哪自,這世上最難降的妖魔是什么丰包? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮壤巷,結(jié)果婚禮上邑彪,老公的妹妹穿的比我還像新娘。我一直安慰自己胧华,他們只是感情好锌蓄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布升筏。 她就那樣靜靜地躺著,像睡著了一般瘸爽。 火紅的嫁衣襯著肌膚如雪您访。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天剪决,我揣著相機(jī)與錄音灵汪,去河邊找鬼。 笑死柑潦,一個胖子當(dāng)著我的面吹牛享言,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播渗鬼,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼览露,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了譬胎?” 一聲冷哼從身側(cè)響起差牛,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎堰乔,沒想到半個月后偏化,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镐侯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年侦讨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苟翻。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡韵卤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出崇猫,到底是詐尸還是另有隱情沈条,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布邓尤,位于F島的核電站拍鲤,受9級特大地震影響贴谎,放射性物質(zhì)發(fā)生泄漏汞扎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一擅这、第九天 我趴在偏房一處隱蔽的房頂上張望澈魄。 院中可真熱鬧,春花似錦仲翎、人聲如沸痹扇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喷众。三九已至奋救,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間结笨,已是汗流浹背包晰。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炕吸,地道東北人伐憾。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像赫模,于是被迫代替她去往敵國和親树肃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容