setImmediate和setTimeout上面的這個流程說簡單點(diǎn)就是在一個異步流程里,setImmediate會比定時器先執(zhí)行,我們寫點(diǎn)代碼來試試:
console.log('outer');setTimeout(() => {setTimeout(() => {console.log('setTimeout');}, 0);setImmediate(() => {console.log('setImmediate');});}, 0);上述代碼運(yùn)行如下:
和我們前面講的一樣,setImmediate先執(zhí)行了 。我們來理一下這個流程:
外層是一個setTimeout,所以執(zhí)行他的回調(diào)的時候已經(jīng)在timers階段了處理里面的setTimeout,因?yàn)楸敬窝h(huán)的timers正在執(zhí)行,所以他的回調(diào)其實(shí)加到了下個timers階段處理里面的setImmediate,將它的回調(diào)加入check階段的隊(duì)列外層timers階段執(zhí)行完,進(jìn)入pending callbacks,idle, prepare,poll,這幾個隊(duì)列都是空的,所以繼續(xù)往下到了check階段,發(fā)現(xiàn)了setImmediate的回調(diào),拿出來執(zhí)行然后是close callbacks,隊(duì)列時空的,跳過又是timers階段,執(zhí)行我們的console
但是請注意我們上面console.log(‘setTimeout’)和console.log(‘setImmediate’)都包在了一個setTimeout里面,如果直接寫在最外層會怎么樣呢?代碼改寫如下:
console.log('outer');setTimeout(() => {console.log('setTimeout');}, 0);setImmediate(() => {console.log('setImmediate');});我們來運(yùn)行下看看效果:
好像是setTimeout先輸出來,我們多運(yùn)行幾次看看:
怎么setImmediate又先出來了,這代碼是見鬼了還是啥?這個世界上是沒有鬼怪的,所以事情都有原因的,我們順著之前的Event Loop再來理一下 。在理之前,需要告訴大家一件事情,node.js里面setTimeout(fn, 0)會被強(qiáng)制改為setTimeout(fn, 1),這在官方文檔中有說明 。(說到這里順便提下,HTML 5里面setTimeout最小的時間限制是4ms) 。原理我們都有了,我們來理一下流程:
外層同步代碼一次性全部執(zhí)行完,遇到異步API就塞到對應(yīng)的階段遇到setTimeout,雖然設(shè)置的是0毫秒觸發(fā),但是被node.js強(qiáng)制改為1毫秒,塞入times階段遇到setImmediate塞入check階段同步代碼執(zhí)行完畢,進(jìn)入Event Loop先進(jìn)入times階段,檢查當(dāng)前時間過去了1毫秒沒有,如果過了1毫秒,滿足setTimeout條件,執(zhí)行回調(diào),如果沒過1毫秒,跳過跳過空的階段,進(jìn)入check階段,執(zhí)行setImmediate回調(diào)
通過上述流程的梳理,我們發(fā)現(xiàn)關(guān)鍵就在這個1毫秒,如果同步代碼執(zhí)行時間較長,進(jìn)入Event Loop的時候1毫秒已經(jīng)過了,setTimeout執(zhí)行,如果1毫秒還沒到,就先執(zhí)行了setImmediate 。每次我們運(yùn)行腳本時,機(jī)器狀態(tài)可能不一樣,導(dǎo)致運(yùn)行時有1毫秒的差距,一會兒setTimeout先執(zhí)行,一會兒setImmediate先執(zhí)行 。但是這種情況只會發(fā)生在還沒進(jìn)入timers階段的時候 。像我們第一個例子那樣,因?yàn)橐呀?jīng)在timers階段,所以里面的setTimeout只能等下個循環(huán)了,所以setImmediate肯定先執(zhí)行 。同理的還有其他poll階段的API也是這樣的,比如:
var fs = require('fs')fs.readFile(__filename, () => {setTimeout(() => {console.log('setTimeout');}, 0);setImmediate(() => {console.log('setImmediate');});});這里setTimeout和setImmediate在readFile的回調(diào)里面,由于readFile回調(diào)是I/O操作,他本身就在poll階段,所以他里面的定時器只能進(jìn)入下個timers階段,但是setImmediate卻可以在接下來的check階段運(yùn)行,所以setImmediate肯定先運(yùn)行,他運(yùn)行完后,去檢查timers,才會運(yùn)行setTimeout 。
類似的,我們再來看一段代碼,如果他們兩個不是在最外層,而是在setImmediate的回調(diào)里面,其實(shí)情況跟外層一樣,結(jié)果也是隨緣的,看下面代碼:
console.log('outer');setImmediate(() => {setTimeout(() => {console.log('setTimeout');}, 0);setImmediate(() => {console.log('setImmediate');});});原因跟寫在最外層差不多,因?yàn)閟etImmediate已經(jīng)在check階段了,里面的循環(huán)會從timers階段開始,會先看setTimeout的回調(diào),如果這時候已經(jīng)過了1毫秒,就執(zhí)行他,如果沒過就執(zhí)行setImmediate 。
以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問題,請您及時就醫(yī)或請專業(yè)人士給予相關(guān)指導(dǎo)!
「愛刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對您有所幫助:- 工廠平面圖制作方法 工廠平面設(shè)計圖的步驟
- json數(shù)據(jù)自動生成表格方法 json轉(zhuǎn)excel表格工具
- 申請英國讀大學(xué)的誤區(qū)有哪些
- 米生小黑蟲怎么辦啊
- 牙膏的保質(zhì)期一般多久
- 類似機(jī)車的電動車 適合青少年騎的電動車
- 佛手瓜的皮能吃嗎
- 五花肉腌制方法燒烤
- 抖音文案視頻素材,抖音短視頻的文案怎樣寫
- 牛板筋是牛的哪個部位
