<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
首先我們來看一道題目,如下javascript程式碼,執行後會在控制檯列印出什麼內容?
async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { console.log('async2 start'); return new Promise((resolve, reject) => { resolve(); console.log('async2 promise'); }) } console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); async1(); new Promise(function(resolve) { console.log('promise1'); resolve(); }).then(function() { console.log('promise2'); }).then(function() { console.log('promise3'); }); console.log('script end')
說實話,真正能在面試中把這道題目答對的前端工程師鳳毛麟角。我們先來瞧一下答案吧。把以上程式碼存到test.js檔案中,並用node執行一下,結果如下:
如果把以上程式碼貼到一個網頁中的script標籤裡面,然後開啟這個網頁,再開啟控制檯,可以看到如下輸出(Chrome 64位元 63.0.3239.84):
結果和node列印的一模一樣。那麼為什麼是這個順序呢?
我們都知道js的單執行緒特性(html5的web worker不算在內~)以及良好的非同步支援。在單執行緒的前提下,非同步任務到底什麼時候開始執行,其實是有兩個佇列來進行管理,即Macrotask和Microtask(只有一個字母的差距,不要認錯……)。在當前正在執行的執行緒中,如果碰到屬於Macrotask的非同步任務,則放入Macrotask佇列;碰到Microtask的非同步任務則放入Microtask佇列。注意這裡只是把任務放入佇列,並不會執行它。等到當前主執行緒任務執行完畢之後,會依次從Microtask佇列中取出任務執行,在執行期間當然還是遵循碰到非同步任務放入相應佇列的原則。等到Microtask任務全部執行過了,此時再從Macrotask佇列中取出一個任務執行。
屬於Macrotask的任務有:
setTimeout,setInteveral,script標籤,I/O,UI渲染
屬於Microtask的任務有:
Promise,async/await,process.nextTick,Object.observe,MutationObserver
(事實上,即使同樣是Microtask,內部也是有優先順序的差別的,例如NodeJS的實現上,process.nextTick比Promise要先執行。相關問題可以瞧瞧這個連線:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ 。反正我瞧到一半就放棄了,好在async/await和Promise沒有優先順序差別)
然後我們來分析一下本題中的執行順序:
【1】第15行執行,列印出script start
【2】第16至18行,把回撥任務放入Macrotask (目前Macrotask:第16行setTimeout,Microtask:空)
【3】第20行,執行async1函數,先列印出第2行的async1 start
【4】第3行的async2先執行,列印出第8行的async2 start
【5】第9行至第12行遇到Promise,先列印出第11行的async2 promise(注意不管你resolve寫在new Promise的函數什麼位置,都跟寫到最後一句一樣!)
【6】第3行的async2返回了Promise,並且async2前面有await修飾,因此後面第4行的任務被放到Microtask(目前Macrotask:第16行setTimeout,Microtask:第4行)
【7】第22至25行,列印出promise1,並把第26行放入Microtask,注意第28行還沒執行到,所以這行什麼都不做(目前Macrotask:第16行setTimeout,Microtask:第4行,第26行)
【8】第30行列印script end(目前Macrotask:第16行setTimeout,Microtask:第4行,第26行)
【9】指令碼主執行緒執行結束,現在拿出來一個Microtask,即第4行,列印async1 end(目前Macrotask:第16行setTimeout,Microtask:第26行)
【10】再拿出來一個Microtask,即第26行,列印promise2,此時由於第26行後面跟著then,所以把第28行插入Microtask(目前Macrotask:第16行setTimeout,Microtask:第28行)
【11】再拿出來一個Microtask,即第28行,列印promise3(目前Macrotask:第16行的setTimeout,Microtask:空)
【12】Microtask沒有了,執行下一個Macrotask,即第16行的setTimeout,列印setTimeout,結束
需要注意的是,以下兩種寫法,效果是一模一樣的(resolve的位置無所謂):
寫法1: new Promise((resolve, reject) => { console.log('1111'); resolve(); console.log('2222'); }); 寫法2: new Promise((resolve, reject) => { console.log('1111'); console.log('2222'); resolve(); });
另外,對於Promise的鏈式呼叫,如new Promise(....).then(...).then(...)....,一次只放第一個then的內容進入Microtask,等第一個then執行的時候,會把第二個then放入Microtask,而不是一次把兩個then都放進去。
以上就是Javascript中Microtask和Macrotask鮮為人知的知識點的詳細內容,更多關於Javascript中Microtask和Macrotask的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45