本文作者:駐雲科技,孫大慶
nodejs裡有一個方法經常用到叫process.nexttick, 但是可能大部分人沒有弄清楚這個方法的原理是什麼,它到底比settimeout()到底快在哪裡?
在nodejs的文檔裡,對這個方法的解釋是:
the 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.
這段說明不難了解,但是有一個重要的概念沒有說清楚,就是什麼是next tick queue, 接下來我們試圖說明這個問題。
我們知道nodejs處理回調底層使用的是libuv, libuv在處理事件回調的時候有三種方式,也就是uv_run啟動event loop時的第二個參數,參照libuv的文檔如下:
uv_run_default:runs the event loop until there are no more active and referenced handles orrequests. returns non-zero if uv_stop() was called and there are still activehandles or requests. returns zero in all other cases.
uv_run_once:poll for i/o once. note that this function blocks if there are no pendingcallbacks. returns zero when done (no active handles or requests left), ornon-zero if more callbacks are expected (meaning you should run the event loopagain sometime in the future).
uv_run_nowait: pollfor i/o once but don’t block if there are no pending callbacks. returns zero ifdone (no active handles or requests left), or non-zero if more callbacks areexpected (meaning you should run the event loop again sometime in the future).
uv_run_default: 這個值的功能是處理所有的事件回調,直到沒有事件回調可以處理才傳回, 否則一直阻塞。
uv_run_once: 顧名思義,這個值的功能是等待一次i/o事件的發生,并處理相關回到函數,然後傳回,如果還有事件回調需要處理,則傳回非零,否則傳回零。
·uv_run_nowait·:同樣,字面意思是不等待i/o事件,有需要處理的事件就處理,否則立即傳回,傳回值和上面一緻。
那麼下面我們看看nodejs源碼是怎麼使用的,上源碼:
startnodeinstance 函數是nodejs啟動一個node執行個體的函數,其中有如下循環:
可以看到uv_run先後使用了uv_run_once和uv_run_nowait,這樣的話,每一次事件觸發,都會導緻這個循環執行一次。
是以結論就是每一次這個循環的執行,算作一個tick, 那麼queue是怎麼來的, 看看node.js源碼
...
nexttick的源碼告訴我們,他隻是将一個callback壓入一個隊列,等待下一個tick執行, 這就是傳說中的next tick queue, 其之是以快,是應為settimeout需要調用系統調用并等待作業系統核心觸發計時器事件,而nexttick不用,下一次的tick自動執行。
本次的【技術幹貨】分享内容,是不是意猶未盡呢?那就快關注我們的微信公衆号“架構雲專家頻道”吧,精彩内容,每日奉上!