[Node] Macrotask和Microtask Queue在Node端的不同表現(xiàn)

1. 背景

我們知道萤捆,v8在處理setTimeout和Promise的時候,
會區(qū)分Macrotask Queue和Microtask Queue栈幸。

setTimeout會將task放到Macrotask Queue中击费,
而Promise會將task放到Microtask Queue中。

一開始執(zhí)行的代碼在Macrotask Queue中楞遏。

v8在執(zhí)行代碼的時候茬暇,
(1)首先從Macrotask Queue中取出一個task執(zhí)行首昔,
(2)執(zhí)行完后,再從Microtask Queue中依次取出所有的task順序執(zhí)行糙俗,
(3)等這些Microtask Queue中的task都執(zhí)行完勒奇,再進(jìn)行第(1)步開始循環(huán)執(zhí)行。

2. 場景

以上執(zhí)行過程在瀏覽器環(huán)境中是沒有問題的巧骚,
但是在Node環(huán)境中赊颠,第(1)條卻有些出入。

在Node環(huán)境中劈彪,
從Macrotask Queue中竣蹦,也是依次取出所有的task順序執(zhí)行
而不是只取出一個task執(zhí)行沧奴。

2.1 示例代碼

console.log(1);

setTimeout(() => {
    console.log(2);
    new Promise((res, rej) => {
        console.log(3);
        res();
    }).then(() => {
        console.log(4);
    });
}, 0);

new Promise((res, rej) => {
    console.log(5);
    res();
}).then(() => {
    console.log(6);
});

setTimeout(() => {
    console.log(7);
    new Promise((res, rej) => {
        console.log(8);
        res();
    }).then(() => {
        console.log(9);
    });
}, 0);

2.2 瀏覽器環(huán)境

Chrome 62.0.3202.94(正式版本)(64 位)
Safari 10.0.3 (12602.4.8)
Firefox 57.0.2 (64-bit)

1
5
6
2
3
4
7
8
9

在瀏覽器環(huán)境中痘括,一開始所有代碼的都在Macrotask Queue中,
取出來開始執(zhí)行滔吠,console.log(1);纲菌,
緊接著,遇到setTimeout疮绷,于是將以下task放到Macrotask Queue中翰舌,

console.log(2);
new Promise((res, rej) => {
    console.log(3);
    res();
}).then(() => {
    console.log(4);
});

隨后,console.log(5);跟著new Promise立即執(zhí)行冬骚,
.then則將console.log(6);放到了Microtask Queue中椅贱。

最后,后面的第二個setTimeout只冻,又將以下task放到了Macrotask Queue中庇麦,

console.log(7);
new Promise((res, rej) => {
    console.log(8);
    res();
}).then(() => {
    console.log(9);
});

第(1)步,執(zhí)行完畢属愤。

然后按著v8執(zhí)行流程女器,開始第(2)步,
從Microtask Queue中依次取出所有的task順序執(zhí)行住诸。
目前Microtask Queue中只有console.log(6);驾胆,執(zhí)行完畢涣澡。

接著下一輪循環(huán),又重新開始第(1)步丧诺,
從Macrotask Queue中取出一個task執(zhí)行入桂,將取出以下task,

console.log(2);
new Promise((res, rej) => {
    console.log(3);
    res();
}).then(() => {
    console.log(4);
});

于是驳阎,先執(zhí)行console.log(2);抗愁,
然后console.log(3);跟著new Promise一起執(zhí)行。
最后呵晚,.thenconsole.log(4);放到Microtask Queue中蜘腌。

分歧點(diǎn):====> ====> ====> ====> ====> ====> ====> ====>
下面就出現(xiàn)了瀏覽器環(huán)境和Node環(huán)境的分歧了。

這時候根據(jù)v8執(zhí)行流程第(1)步饵隙,已經(jīng)執(zhí)行了一個task撮珠,
該從Microtask Queue中依次取出所有的task順序執(zhí)行了。

瀏覽器環(huán)境中金矛,確實是這么執(zhí)行的芯急,
這時候Microtask Queue中只有console.log(4);,執(zhí)行它驶俊。

然后就下一輪循環(huán)了娶耍,重新執(zhí)行第(1)步,
從Macrotask Queue中取出一個task執(zhí)行饼酿,
將取出以下task榕酒,

console.log(7);
new Promise((res, rej) => {
    console.log(8);
    res();
}).then(() => {
    console.log(9);
});

先執(zhí)行console.log(7);
然后console.log(8);跟著new Promise一起執(zhí)行嗜湃。
最后奈应,.thenconsole.log(9);放到Microtask Queue中。

Macrotask Queue中的這個task執(zhí)行完了购披,該執(zhí)行第(2)步了杖挣,
從Microtask Queue中依次取出所有的task順序執(zhí)行,
這時候Microtask Queue中只有console.log(9);刚陡,執(zhí)行它惩妇。

于是,瀏覽器端就得到了以上輸出筐乳。

2.3 Node環(huán)境

v 6.12.0
v 8.9.1

1
5
6
2
3
7
8
4
9

Node環(huán)境中歌殃,以上執(zhí)行過程,在分歧點(diǎn)之前都是一樣的蝙云。
在Node環(huán)境中氓皱,并不會一次只從Macrotask Queue中取出一個task執(zhí)行,
而是和Microtask Queue一樣,取出所有的task依次執(zhí)行波材。

因此股淡,在分歧點(diǎn)處,
一個Macrotask Queue中的task執(zhí)行完后廷区,還會再次取task唯灵,得到了,

console.log(7);
new Promise((res, rej) => {
    console.log(8);
    res();
}).then(() => {
    console.log(9);
});

先執(zhí)行console.log(7);隙轻,
然后console.log(8);跟著new Promise一起執(zhí)行埠帕。
最后,.thenconsole.log(9);放到Microtask Queue中玖绿。

這時候Macrotask Queue中已經(jīng)沒有task了敛瓷,
這才開始從Microtask Queue中依次取出所有的task順序執(zhí)行。
此時镰矿,Microtask Queue中有以下兩個task琐驴,
console.log(4);console.log(9);俘种。

于是秤标,Node端就得到了以上輸出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宙刘,一起剝皮案震驚了整個濱河市苍姜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悬包,老刑警劉巖衙猪,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異布近,居然都是意外死亡垫释,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門撑瞧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棵譬,“玉大人,你說我怎么就攤上這事预伺《┫蹋” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵酬诀,是天一觀的道長脏嚷。 經(jīng)常有香客問我,道長瞒御,這世上最難降的妖魔是什么父叙? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上趾唱,老公的妹妹穿的比我還像新娘屿岂。我一直安慰自己,他們只是感情好鲸匿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布爷怀。 她就那樣靜靜地躺著,像睡著了一般带欢。 火紅的嫁衣襯著肌膚如雪运授。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天乔煞,我揣著相機(jī)與錄音吁朦,去河邊找鬼。 笑死渡贾,一個胖子當(dāng)著我的面吹牛逗宜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播空骚,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼纺讲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了囤屹?” 一聲冷哼從身側(cè)響起熬甚,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肋坚,沒想到半個月后乡括,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡智厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年诲泌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铣鹏。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡敷扫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吝沫,到底是詐尸還是另有隱情呻澜,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布惨险,位于F島的核電站羹幸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辫愉。R本人自食惡果不足惜栅受,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屏镊,春花似錦依疼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至棍丐,卻和暖如春误辑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背歌逢。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工巾钉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秘案。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓砰苍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親阱高。 傳聞我的和親對象是個殘疾皇子赚导,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345