iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 21
0
Modern Web

一步一腳印-紮紮實實學es6系列 第 21

非同步學習入門-消息隊列的執行順序

javascript 是單執行緒的程式
意味著一次只能做一件事
但是想像一下我們一個人在廚房煮菜,有好幾個爐子
我們只有「一個人」但是我們不會一直等待一道菜煮好了才煮下一道菜
我們會來回切換煮不同的菜
比如先把湯的料切好了就先倒進鍋子煮開著讓他煮
就可以去忙第2道菜

等湯煮好了後我們就把他拿起來,再煮別的菜
所以這種來回切換煮不同的菜
我們把他稱為非同步模式

一般我們在es5中最基本常用的就是
js的內建函式 setTimeout()setTimeInterval()
跟JQuery的ajax()
上述3個應該沒有人不會,我們就不多闡述
在es6 中,我們要來學的有Promise/Generator/async/await
這些會在系列文中一一來學習

消息隊列

在消息隊列中,是採取先進先出(FIFO)的方式
在這邊的消息,可以看作TASK

TASK 我們又分為task 與 micro task
哪些在js 中算是task ,哪些是micro task 呢

目前大約歸類如下(更多的之後有看到再補上)
TASK:

  • DOM 事件操作
  • 用戶事件
  • 定時器
  • AJAX
    MICRO TASK:
  • promise內的then
  • eventListener

而區分為這個有什麼用呢
在這邊區分這個為的是要搞清楚執行順序

在 globalEC的TASK會先執行
所以要考慮的是
在globalEC 執行完後,TASK 與MICRO TASK 中
什麼會先被放到Global EC中

其實是一個loop 的概念
MICRO TASK 會先被放進Global EC
再放TASK 的
執行完後,再去檢查micro task 中還有沒有待執行的任務
有的話再放進 GlobalEC,放完後再去檢查task 隊列
我們來看一下範例

console.log("1.直接進 globalEC");
setTimeout(()=>console.log("2.setTimeout這個是TASK LIST"),0);
new Promise((resolve,reject)=>{
	console.log("3.Promise 的, 但他會直接進globalEC");
	resolve();
}).then(()=>console.log("4.then這個會進micro task list"));

初步可以觀察為以下現象

  1. console.log("直接進globalEC"); 放進global EC, 立即執行,執行完即移出EC
  2. 將setTimeout 放進taskList 中,不處理
  3. 將promise內的console.log()放進globalEC 中,立即執行,執行完移出ec
  4. 將promise內的resolve()放進globalEC中
  5. 將promise.then 放進micro task 中
  6. globacl EC 任務結束,檢查micro task list
  7. 將micro task list 中的 promise.then()的console.log()放進globalEC中,執行完移出ec
  8. 檢查task list ,將setTimeout 中的console.log()放進globalEC 中,執行完移出ec

所以console的順序為 1 3 4 2
https://ithelp.ithome.com.tw/upload/images/20181021/20110579zCQON3wjg8.png

如果有誤再請大家指正,謝謝


上一篇
閉包(2) 執行環境的現象
下一篇
非同步入門(2) 計時器
系列文
一步一腳印-紮紮實實學es630

尚未有邦友留言

立即登入留言