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