远古时候,在北方荒野中,有座巍峨雄伟、高耸入云的高山。在山林深处,生活着一群力大无穷的巨人。他们的首领,是幽冥之神“后土”的孙儿,“信”的儿子,名字叫做夸父。因此这群人就叫夸父族。他们手速极快,思维敏捷,逻辑缜密,左拥度娘,右抱谷歌,气概非凡。而且还心地善良,勤劳勇敢,过着与世无争,逍遥自在的日子。
那时候bug遍地,需求横行,人们生活凄苦。夸父为使本部落的人们能够活下去,每天都率领众人跟产品搏斗。
夸父常常将自己开发出来的页面,挂在自己的两只耳朵上作为装饰,抓在手上挥舞,引以为荣。
有一年的天气非常热,火辣辣的太阳直射在大地上,烤死庄稼,晒焦树木,河流干枯。人们热得难以忍受,夸父族的人纷纷死去。
而这颗太阳的内核写满了代码:
<script>
setTimeout(() => {
console.log(5)
}, 10)
setTimeout(() => {
console.log(4)
}, 0)
new Promise(resolve => {
console.log(1);
resolve();
}).then(() => {
console.log(3)
})
console.log(2)
</script>
炽热的阳光照射下,空气都在沸腾,这密密麻麻的代码扭曲成一个邪恶的笑容,不仅在涂炭生灵,似乎还在嘲笑着夸父的无能 。
夸父看到这种情景很难过,他仰头望着太阳,告诉族人:“太阳实在是可恶,我要追上太阳,掌握它,让它听我的指挥。”族人听后纷纷劝阻。
有的人说:“你千万别去呀,太阳离我们那么远,你会累死的。”
有的人说:“太阳那么热,你会被烤死的。”
有的人说:“太阳那么难,你会掉光头发的。”
夸父心意已决,发誓要捉住太阳,让它听从人们的吩咐,为大家服务。他看着愁苦不堪的族人,说:“为大家的幸福生活,我一定要去。”
太阳刚刚从海上升起,夸父告别族人,怀着雄心壮志,从东海边上向着太阳升起的方向,迈开大步追去,开始他逐日的征程。
太阳在空中飞快地移动,夸父在地上如疾风似的,拼命地追呀追。他穿过一座座大山,跨过一条条河流,大地被他的脚步,震得“轰轰”作响,来回摇摆。
没有什么能阻碍他对破解太阳难题的渴望。
夸父跑累的时候,就微微打个盹,将鞋里的土抖落在地上,于是形成大土山。饿的时候,他就摘野果充饥,有时候夸父也煮饭。他用三块石头架锅,这三块石头,就成了三座鼎足而立的高山,有几千米高。
经管刺眼,夸父那坚定的眼神却死死盯着太阳里写的代码,慢慢的,心里演化出道道顿悟。
“js是单线程语言,为了不被一些操作(setTimeout、io操作、promise)因等待而阻塞线程,js便使用了异步的事件轮询,在执行script标签内的代码时,遇到异步操作,便会将其放入任务队列” 向promise传入的函数是同步任务,promise后接的then是异步任务。
<script>
setTimeout(() => {
console.log(5)
}, 10)
setTimeout(() => {
console.log(4)
}, 0)
new Promise(resolve => {
console.log(1);
resolve();
}).then(() => {
console.log(3)
})
console.log(2)
</script>
如果只有一个任务队列的话,理论上的输出结果:1 2 4 3 5
其中执行过程为下图:
每次事件轮询,都会询问任务队列中的每一个任务,执行可执行的任务,然后本次事件轮询就结束了。
夸父默默说出了1 2 4 3 5,然而太阳并没有消失,反而发出了更为炽热的光线,它们就像火焰一般,灼烧着夸父身旁的一切,衣服瞬间化为乌有,皮肤上甚至发出了滋滋的声响,更为严重的是夸父的眼睛直接被灼烧致盲。
夸父双手捂住眼睛,尽管很疼,但他却没哼一声,内心的顿悟却越发明亮。
“js的任务队列有两个,宏任务和微任务队列,而不同的异步任务会被放入不同的队列。”
其中:
-
script整体代码
-
setTimeout
-
setInterval
-
setImmediate
-
I/O 这些任务会被放入宏任务队列
-
process.nextTick
-
promise后面跟的then的入参
-
async/await(本质就是promise) 这些任务会被放入微任务队列
然后这只能得到下图:
输出1 2,后面是怎样的执行顺序依旧不知道。
不行,尽管眼睛看不见了,夸父依旧能通过感受炽烈的阳光来判断太阳的方向,为了族人,为了破解太阳难题。
夸父依旧追着太阳跑,眼看离太阳越来越近,他的信心越来越强。越接近太阳,就渴得越厉害,已经不是捧河水就可以止渴的了。但是,他没有害怕,并且一直鼓励着自己,“快了,就要追上太阳了,人们的生活就会幸福了。”
经过九天九夜,在太阳落山的地方,夸父终于追上了它。红彤彤、热辣辣的火球,就在夸父眼前。
此时此刻,他的头上,万道金光,沐浴在他身上,他的体内也孕育着别样的光彩。
“原来”
宏任务队列和微任务队列两者之间的执行顺序是:从宏任务队列取出一个任务执行,这个任务会产生许多微任务,并将它们放入微任务队列,待这个宏任务执行完之后,会执行微任务队列中的所有任务。待微任务队列为空,就从宏任务中取出一个新的任务执行,周而复始,生生不息。
在一次事件轮询过程中:宏任务 -> 微任务 -> UIrender
事件轮询的结束条件是:事件轮询开始时的宏任务队列中的任务都被轮询过,且微任务队列为空,即为一次事件轮询的结束。
所以太阳难题的答案是:1 2 3 4 5
其中的执行过程如下图:
太阳的光芒慢慢的变得温和起来,尽管又渴又累,夸父依然无比欢欣地张开双臂,把太阳抱住了。
“叮”,黄河之水天上来,缓解了夸父的口渴,但这还远远不够。
“叮”,渭河之水东边来,再一次缓解了夸父的口渴,但,还不够。
“哗”,千里大泽北涌来,高达数万丈的水浪,如同垂天之幕,在太阳的照射下,宛如神光,这下,夸父终于解渴了。
从此,地上的生灵不在饱受酷热煎熬,夸父族也回复了往日的幸福安康的生活。