摘要:對(duì)了,我記得你提到了,它是什么不是說使用的是嗎,它和又有什么關(guān)系未完待續(xù)其他問答方式學(xué)一參考是用來做什么的廠長的回答更快的異步函數(shù)和
Q: 好了,我們繼續(xù)談?wù)?Node.js 吧,我記得上次說到了「非阻塞」和「事件驅(qū)動(dòng)」,這引起了我的好奇心,但是又給我潑了一桶冷水,這兩個(gè)詞有點(diǎn)高端。
A:別急,我們先來看一個(gè)簡單的場(chǎng)景:
人人網(wǎng)刷朋友新鮮事你應(yīng)該用過吧?實(shí)現(xiàn)這樣的功能有一種簡單的方式,是讓用戶與服務(wù)器之間保持一個(gè)長輪詢。
但是它與普通的 Ajax 不一樣,服務(wù)器不會(huì)立馬返回信息,它會(huì)先 hold 住,等待應(yīng)該返回信息了,它才會(huì)返回信息(比如你的好友發(fā)了一條新的狀態(tài))。
從傳統(tǒng)服務(wù)端來看(比如 Apache),每次一個(gè)新用戶連到你的網(wǎng)站上,你的服務(wù)器得新開一個(gè)連接,每個(gè)連接都需要占用一個(gè)線程,這些線程大部分都是閑著的(比如等你的好友發(fā)狀態(tài),查數(shù)據(jù)庫等),雖然它們是閑著的,但是照樣占用了內(nèi)存,也就是說,如果用戶達(dá)到一定的規(guī)模,服務(wù)器的內(nèi)存就會(huì)耗光而癱瘓。
解決辦法有很多,比如說使用線程池,但是它依然是阻塞的,如果線程池里的所有線程都被阻塞(網(wǎng)速慢,被人惡意暫用)那么接下來的請(qǐng)求將會(huì)排隊(duì)等待。
Node.js 就不相同了,它使用了「非阻塞」與「事件驅(qū)動(dòng)」模型,你可以把它想象成一個(gè) Event Loop 循環(huán),這個(gè)循環(huán)會(huì)一直跑。一個(gè)新的請(qǐng)求來了,Event Loop 接收這個(gè)請(qǐng)求,然后交給其他線程,比如查詢數(shù)據(jù)庫,然后響應(yīng)一個(gè) callback,接著接收其他請(qǐng)求,而不是等待數(shù)據(jù)庫結(jié)果的返回。
如果數(shù)據(jù)庫返回了結(jié)果,服務(wù)端將會(huì)把它返回給客戶端,并繼續(xù)循環(huán)。這就是事件驅(qū)動(dòng):服務(wù)端只在有事情發(fā)生時(shí),才會(huì)有相應(yīng)的處理(或者是接受請(qǐng)求,或者是一些 callback)。
Q:這么看來,Node.js 的非阻塞和事件驅(qū)動(dòng),是基于這個(gè) Event Loop 的?A:是的,簡單來講,Node.js 的 Event Loop 是基于 libuv,而瀏覽器的 Event Loop 則是在 html5 規(guī)范 中定義,具體實(shí)現(xiàn)交給瀏覽器廠商。
Q:有趣了,還有兩種 Event Loop。A:對(duì)比來看,它們有點(diǎn)相似:
在瀏覽器中比較簡單,值得注意的一點(diǎn)是,會(huì)在每個(gè) tasks 之后,會(huì)把當(dāng)前 microtask 隊(duì)列里的任務(wù)都執(zhí)行完:
Node.js 稍微復(fù)雜一點(diǎn),每次 Event Loop 都需要經(jīng)過六個(gè)階段,每一個(gè)階段之后,都會(huì)執(zhí)行 nextTick、microtasks (resolved promise, 等):
┌───────────────────────┐ ┌─>│ timers │ <─── setTimeout/setInterval callback │ └──────────┬────────────┘ ┌─────────────────────────┐ │ │ │ nextTick queue │ │ │ <─────────────── │ │ │ │ │ microTask queue │ │ ┌──────────┴────────────┐ └─────────────────────────┘ │ │ I/O callbacks │ │ └──────────┬────────────┘ ┌─────────────────────────┐ │ │ │ nextTick queue │ │ │ <─────────────── │ │ │ │ │ microTask queue │ │ ┌──────────┴────────────┐ └─────────────────────────┘ │ │ idle, prepare │ <─── 僅內(nèi)部使用 │ └──────────┬────────────┘ │ │ ┌─────────────────────────┐ │ │ │ nextTick queue │ │ │ <──────────────── │ │ │ │ │ microTask queue │ │ │ └─────────────────────────┘ │ │ ┌─────────────────────────┐ │ ┌──────────┴────────────┐ │ incoming: │ │ │ poll │ <────┤ connections, │ │ └──────────┬────────────┘ │ data, etc │ │ │ └─────────────────────────┘ │ │ ┌─────────────────────────┐ │ │ │ nextTick queue │ │ │ <──────────────── │ │ │ │ │ microTask queue │ │ │ └─────────────────────────┘ │ ┌──────────┴────────────┐ │ │ check │ <─── setImmediate callback │ └──────────┬────────────┘ ┌─────────────────────────┐ │ │ │ nextTick queue │ │ │ <─────────────── │ │ │ │ │ microTask queue │ │ ┌──────────┴────────────┐ └─────────────────────────┘ │ │ close callbacks │ <─── eg: socket.on("close",func) │ └──────────┬────────────┘ ┌─────────────────────────┐ │ │ │ nextTick queue │ │ │ <─────────────── │ │ └─────────────┴ │ microTask queue │ └─────────────────────────┘
來一段簡單的代碼,猜猜瀏覽器(Chrome)和 Node.js 分別輸出什么:
console.log("start"); setTimeout(() => { console.log("timer1"); Promise.resolve().then(() => { console.log("promise1"); }); }, 0); setTimeout(() => { console.log("timer2"); Promise.resolve().then(() => { console.log("promise2"); }); }, 0); console.log("end");Q:瀏覽器 (Chrome) 中肯定是輸出 start、end、time1、promise1、time2、promise2,至于 Node.js 中,我猜也是一樣的吧?
A:我們先來驗(yàn)證一下:
瀏覽器中:
start end timer1 promise1 timer2 promise2
Node.js 中:
start end timer1 timer2 promise1 promise2
看來和想象中的不一樣,別急,看個(gè)動(dòng)圖就會(huì)明白了:
瀏覽器中:
Node.js 中:
Q:原來是這樣,那如果在每個(gè) setTimeout callback 里加上 process.nextTick 那么是比 Promise.then 先執(zhí)行?A:是的,還記得上面所說過的嗎,在每個(gè)階段后都會(huì)執(zhí)行 nextTick queue 以及 micktasks queue,nextTick queue 的優(yōu)先級(jí)比 micktasks queue 高。
Q:我懂了。對(duì)了,我記得你提到了 libuv,它是什么?不是說 Node.js 使用的是 v8 嗎,它和 v8 又有什么關(guān)系?A:...
未完待續(xù)...
其他問答方式學(xué) Node.js(一)
參考https://blog.csdn.net/wtopps/...
Node.js 是用來做什么的? - 廠長的回答
Promises, Next-Ticks and Immediates— NodeJS Event Loop Part 3
更快的異步函數(shù)和 Promise
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101074.html
摘要:就是一個(gè)用于搭建類似于網(wǎng)頁版知乎這種表單項(xiàng)繁多,且內(nèi)容需要根據(jù)用戶的操作進(jìn)行修改的網(wǎng)頁版應(yīng)用。單頁應(yīng)用程序顧名思義,單頁應(yīng)用一般指的就是一個(gè)頁面就是應(yīng)用,當(dāng)然也可以是一個(gè)子應(yīng)用,比如說知乎的一個(gè)頁面就可以視為一個(gè)子應(yīng)用。 最近在逛各大網(wǎng)站,論壇,以及像SegmentFault等編程問答社區(qū),發(fā)現(xiàn)Vue.js異?;鸨貜?fù)性的提問和內(nèi)容也很多,樓主自己也趁著這個(gè)大前端的熱潮,著手學(xué)習(xí)了一...
稍微整理了一下自己平時(shí)看到的前端學(xué)習(xí)資源,分享給大家。 html MDN:Mozilla開發(fā)者網(wǎng)絡(luò) SEO:前端開發(fā)中的SEO css 張?chǎng)涡瘢簭場(chǎng)涡竦牟┛?css精靈圖:css精靈圖實(shí)踐 柵格系統(tǒng):詳解CSS中的柵格系統(tǒng) 媒體查詢:css媒體查詢用法 rem布局:手機(jī)端頁面自適應(yīng)布局 移動(dòng)前端開發(fā)之viewport的深入理解:深入理解viewport 淘寶前端布局:手機(jī)淘寶移動(dòng)端布局 fl...
摘要:前言月份開始出沒社區(qū),現(xiàn)在差不多月了,按照工作的說法,就是差不多過了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來說,差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議那么今天我就把看過的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開始出沒社區(qū),現(xiàn)在差不多9月了,按照工作的說法,就是差不多過了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來說,差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議!那么今天我就...
摘要:雖然程序員有時(shí)候很喜歡自黑風(fēng)格也比較獨(dú)特,但程序員也只是會(huì)編程的普通人,和其他的廚師教師公務(wù)員并沒有什么區(qū)別。 前言 今天是1024程序員節(jié),中國500w+的程序員今天可以享受一天專屬的節(jié)日,網(wǎng)絡(luò)上也有各種慶祝方式: 一些公司祭出了程序員鼓勵(lì)師 showImg(https://segmentfault.com/img/remote/1460000016788859); 一些公司給程序員...
閱讀 2524·2023-04-25 17:27
閱讀 1835·2019-08-30 15:54
閱讀 2377·2019-08-30 13:06
閱讀 2990·2019-08-30 11:04
閱讀 757·2019-08-29 15:30
閱讀 737·2019-08-29 15:16
閱讀 1740·2019-08-26 10:10
閱讀 3612·2019-08-23 17:02