摘要:引言作為服務(wù)器的優(yōu)勢(shì)就在于適合處理高并發(fā)的請(qǐng)求,對(duì)于網(wǎng)站后臺(tái)這種密集型的后臺(tái)尤其有優(yōu)勢(shì),其核心就在于是一個(gè)異步非阻塞模型。關(guān)于異步,同步,阻塞,非阻塞這些概念,本文不做討論。另外兩個(gè)的調(diào)用時(shí)間需要判斷是否都在主線程中被執(zhí)行。
引言
node作為服務(wù)器的優(yōu)勢(shì)就在于適合處理高并發(fā)的請(qǐng)求,對(duì)于web網(wǎng)站后臺(tái)這種I/O密集型的后臺(tái)尤其有優(yōu)勢(shì),其核心就在于node是一個(gè)異步非阻塞模型。關(guān)于異步,同步,阻塞,非阻塞這些概念,本文不做討論。
node的單線程模型js作為單線程語言,有自己的一套運(yùn)行機(jī)制
同步任務(wù)運(yùn)行在主線程上,異步的所有任務(wù)都會(huì)在另一個(gè)隊(duì)列中等待執(zhí)行,一旦同步任務(wù)執(zhí)行完畢開始執(zhí)行異步隊(duì)列中的任務(wù),此時(shí)可以認(rèn)為將第一個(gè)異步隊(duì)列中的任務(wù)移到主線程,一旦再產(chǎn)生異步操作,就會(huì)繼續(xù)往異步隊(duì)列中添加,以此循環(huán)。這就是為什么promise,setTimeout,setInterval,process.nextTick,setImmediate,ajax請(qǐng)求,看起來雖然位于代碼的上面部分卻沒有被按順序執(zhí)行。
看一下node的eventloop的機(jī)制,也就是node實(shí)現(xiàn)異步的架構(gòu)。
主要的不同點(diǎn)是用LIBUV去將隊(duì)列中的任務(wù)形成一個(gè)eventloop,作為下一個(gè)循環(huán)需要執(zhí)行的工作。
觀察者模式的體現(xiàn)個(gè)人一直認(rèn)為js的異步回調(diào)是一種觀察者模式的體現(xiàn),訂閱/發(fā)布,網(wǎng)上的說法是有三種觀察者
idle觀察者:顧名思義,就是早已等在那里的觀察者,以后會(huì)說到的process.nextTick就屬于這類I/O觀察者:顧名思義,就是I/O相關(guān)觀察者,也就是I/O的回調(diào)事件,如網(wǎng)絡(luò),文件,數(shù)據(jù)庫I/O等
check觀察者:顧名思義,就是需要檢查的觀察者,后面會(huì)說到的setTimeout/setInterval就屬于這類
優(yōu)先級(jí)idle觀察者>I/O觀察者>check觀察者
詳細(xì)鏈接
但是個(gè)人看法setTimeout()和setInterval()可以歸為一類觀察者,算是timer觀察者,setImmediate()是check觀察者,至于原因后面回說明
以下是自己對(duì)setTimeout(),setImmediate()和process.nextTick()的比較
首先所有討論均是建立在node的基礎(chǔ)上,三個(gè)函數(shù)也都只比較分析node 中情況,摘自node文檔
setTimeout()callbackThe function to call when the timer elapses.
delayThe number of milliseconds to wait before calling the callback. Schedules execution of a one-time callback after delay milliseconds. Returns a Timeout for use with clearTimeout().
The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.
這里明確了兩點(diǎn),一個(gè)是settimeout的實(shí)際執(zhí)行時(shí)間必然晚于設(shè)置時(shí)間,作精確定時(shí)器根本就是違背他的設(shè)計(jì)意愿的,另外一點(diǎn)就是他的函數(shù)回調(diào)是timer觀察的。
setImmediate()callbackThe function to call at the end of this turn of the Node.js Event Loop
...argsOptional arguments to pass when the callback is called. Schedules the "immediate" execution of the callback after I/O events" callbacks. Returns an Immediate for use with clearImmediate().
When multiple calls to setImmediate() are made, the callback functions are queued for execution in the order in which they are created. The entire callback queue is processed every event loop iteration. If an immediate timer is queued from inside an executing callback, that timer will not be triggered until the next event loop iteration.
核心,回調(diào)會(huì)被立刻放在eventLoop的末尾
process.nextTick()callback
...argsAdditional arguments to pass when invoking the callback he process.nextTick() method adds the callback to the "next tick queue". Once the current turn of the event loop turn runs to completion, all callbacks currently in the next tick queue will be called.
This is not a simple alias to setTimeout(fn, 0). It is much more efficient. It runs before any additional I/O events (including timers) fire in subsequent ticks of the event loop.
文檔中自己就提到了process.nextTick()并非 setTimeout(fn, 0),他更有效率,并且執(zhí)行的序列必在下次所有的event loop的最前列。
比較之后在node文檔中有一個(gè)比較細(xì)致的比較,鏈接
比較這三個(gè)函數(shù),先說process.nextTick(),文檔中說了process.nextTick() is not technically part of the event loop,現(xiàn)在很明確了process.nextTick()并不在event loop里,他回調(diào)的執(zhí)行是在事件等待隊(duì)列之外的,算是優(yōu)先級(jí)最高的插隊(duì)人員,那它作為最優(yōu)先執(zhí)行回調(diào)的就沒有疑問了,實(shí)際的用處就是有一些必須最優(yōu)先執(zhí)行的回調(diào),比如網(wǎng)絡(luò)服務(wù)端中,端口的監(jiān)聽?wèi)?yīng)該必須早于其他事件的回調(diào)。
setImmediate() vs setTimeout()這個(gè)可能是網(wǎng)上說法最不統(tǒng)一的地方了,說誰先執(zhí)行的都有,先測(cè)了下面的代碼
setTimeout(() => { console.log("timeout"); }, 0); setImmediate(() => { console.log("immediate"); });
結(jié)果還真的是隨機(jī)的,這么不嚴(yán)謹(jǐn)?其實(shí)官方對(duì)這個(gè)是有解釋的
The order in which the timers are executed will vary depending on the context in which they are called. If both are called from within the main module, then timing will be bound by the performance of the process (which can be impacted by other applications running on the machine).
However, if you move the two calls within an I/O cycle, the immediate callback is always executed first:
這個(gè)教育了我,真理是有范圍的,所謂普遍真理是形而上學(xué)。所以說setImmediate() vs setTimeout()誰快不能簡(jiǎn)單的說,必須先討論使用的地方。
上面有提到setTimeout(fn, 0)效率不高,至于為什么,暫時(shí)參照國(guó)內(nèi)普遍的說法 該函數(shù)的事件控制,是被維護(hù)在紅黑樹上,那么為了每次去找超時(shí)的回調(diào)必然是logn的復(fù)雜度,而另外兩個(gè)函數(shù)看起來都應(yīng)該是1的復(fù)雜度
總結(jié)綜上個(gè)人傾向于四種觀察者的說法
至于setImmediate() vs setTimeout() vs process.nextTick(),process.nextTick()最快,也有獨(dú)特的應(yīng)用場(chǎng)景。另外兩個(gè)的調(diào)用時(shí)間需要判斷是否都在主線程中被執(zhí)行。
setTimeout(fn, 0)效率偏低。
tip:node官方建議使用setimmediate(),因?yàn)橹辽賾?yīng)用的范圍就可以到瀏覽器端了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107639.html
摘要:標(biāo)準(zhǔn)庫中的所有方法都提供非阻塞的異步版本,并接受回調(diào)函數(shù),某些方法還具有對(duì)應(yīng)的阻塞方法,其名稱以結(jié)尾。比較代碼阻塞方法同步執(zhí)行,非阻塞方法異步執(zhí)行。 阻塞與非阻塞概述 此概述介紹了Node.js中阻塞與非阻塞調(diào)用之間的區(qū)別,此概述將引用事件循環(huán)和libuv,但不需要事先了解這些主題,假設(shè)讀者對(duì)JavaScript語言和Node.js回調(diào)模式有基本的了解。 I/O主要指與libuv支持的...
摘要:而線程是進(jìn)程的一部分,二者相扶相依,其中單線程被稱為輕權(quán)進(jìn)程或輕量級(jí)進(jìn)程,執(zhí)行特性線程只有個(gè)基本狀態(tài)就緒,執(zhí)行,阻塞。以上所述證明了操作與其他函數(shù)的這種區(qū)別是由實(shí)現(xiàn),是用多線程的方式,在標(biāo)準(zhǔn)的阻塞式上模擬非阻塞異步,線程池默認(rèn)限制四線程。 node - 非阻塞的異步 IO 每當(dāng)我們提起 node.js 時(shí)總會(huì)脫口而出 事件驅(qū)動(dòng)、非阻塞I/O 和 單線程,所以我總結(jié)了以下幾點(diǎn)對(duì)這三項(xiàng)概念...
摘要:而線程是進(jìn)程的一部分,二者相扶相依,其中單線程被稱為輕權(quán)進(jìn)程或輕量級(jí)進(jìn)程,執(zhí)行特性線程只有個(gè)基本狀態(tài)就緒,執(zhí)行,阻塞。以上所述證明了操作與其他函數(shù)的這種區(qū)別是由實(shí)現(xiàn),是用多線程的方式,在標(biāo)準(zhǔn)的阻塞式上模擬非阻塞異步,線程池默認(rèn)限制四線程。 node - 非阻塞的異步 IO 每當(dāng)我們提起 node.js 時(shí)總會(huì)脫口而出 事件驅(qū)動(dòng)、非阻塞I/O 和 單線程,所以我總結(jié)了以下幾點(diǎn)對(duì)這三項(xiàng)概念...
摘要:而線程是進(jìn)程的一部分,二者相扶相依,其中單線程被稱為輕權(quán)進(jìn)程或輕量級(jí)進(jìn)程,執(zhí)行特性線程只有個(gè)基本狀態(tài)就緒,執(zhí)行,阻塞。以上所述證明了操作與其他函數(shù)的這種區(qū)別是由實(shí)現(xiàn),是用多線程的方式,在標(biāo)準(zhǔn)的阻塞式上模擬非阻塞異步,線程池默認(rèn)限制四線程。 node - 非阻塞的異步 IO 每當(dāng)我們提起 node.js 時(shí)總會(huì)脫口而出 事件驅(qū)動(dòng)、非阻塞I/O 和 單線程,所以我總結(jié)了以下幾點(diǎn)對(duì)這三項(xiàng)概念...
閱讀 3380·2021-11-25 09:43
閱讀 3189·2021-10-11 10:58
閱讀 2788·2021-09-27 13:59
閱讀 3108·2021-09-24 09:55
閱讀 2198·2019-08-30 15:52
閱讀 1863·2019-08-30 14:03
閱讀 2281·2019-08-30 11:11
閱讀 2050·2019-08-28 18:12