科普一波
- js執(zhí)行是單線程的好啰,執(zhí)行順序是 macro-task -> micro-task -> macro-task -> ... 交替執(zhí)行
- macro-task未舟,以下簡稱macro瞬铸,包含:js整體代碼溶弟、setTimeout仪壮、setInterval、setImmediate湿酸、IO婿屹、UI rendering
- micro-task,以下簡稱micro推溃,包含:process.nextTick昂利、Promises(這里指瀏覽器實現(xiàn)的Promise)、Object.observe(已廢棄)铁坎、MutationObserver
上代碼(執(zhí)行環(huán)境為Node 8.9.4)
setImmediate(function () {
console.log(14);
});
setTimeout(function () {
console.log(13)
});
process.nextTick(function () {
console.log(4);
});
new Promise(function (resolve) {
console.log(1);
for (let i = 0; i < 10000; i++) {
i === 9999 && resolve()
}
console.log(2);
process.nextTick(function () {
console.log(5);
});
}).then(function () {
console.log(6);
process.nextTick(function () {
console.log(10);
});
new Promise(function (resolve) {
console.log(7);
resolve();
console.log(8);
process.nextTick(function () {
console.log(11);
});
}).then(function () {
console.log(9);
process.nextTick(function () {
console.log(12);
});
})
});
console.log(3);
執(zhí)行結(jié)果為 1 2 3 ... 14
開始分析
第一輪
執(zhí)行macro蜂奸,也就是js代碼,輸出1 2 3硬萍;
此時micro中注冊了[4 5 <包含6~12的Promise.then代碼塊>]扩所,macro中注冊了[13 14];
macro已經(jīng)清空朴乖,之后執(zhí)行micro碌奉;第二輪
執(zhí)行micro,輸出4 5寒砖,可以看出process.nextTick優(yōu)先級高于Promise.then赐劣;
接著執(zhí)行micro,執(zhí)行<包含6~12的Promise.then代碼塊>哩都,首先輸出6 7 8魁兼,此時micro再次注冊[10 11 <包含9 12的Promise.then代碼塊>];
接著執(zhí)行micro漠嵌,按照上面得出的結(jié)論咐汞,講道理輸出順序為 10 11 9 12,實際輸出為 9 10 11 12儒鹿,為什么會這樣呢化撕?下面開始分析,純屬猜測T佳住V惨酢!
本人能想到的就是圾浅,micro不止一個掠手,process.nextTick擁有單獨的micro-task隊列;
回頭看<包含6~12的Promise.then代碼塊>狸捕,首先輸出 6 7 8喷鸽,沒毛病灸拍;
此時nextTick獨有的micro注冊了[10 11]做祝,當前micro還注冊了[<包含9 12的Promise.then代碼塊>]砾省;
由于當前micro還沒執(zhí)行完,接著執(zhí)行<包含9 12的Promise.then代碼塊>混槐,此時輸出 9纯蛾,并且向nextTick獨有的micro注冊了12,
此時nextTick獨有的micro包含 [10 11 12]纵隔,這時翻诉,當前micro已經(jīng)清空,接著執(zhí)行nextTick的micro捌刮,輸出 10 11 12碰煌;
這樣就與實際情況相符了~,不過绅作,以上純屬個人猜測B!俄认!最后一輪
執(zhí)行macro个少,輸出 13 14,可以看出setTimeout優(yōu)先級高于setImmediate眯杏;