從HTML5與PromiseA+規(guī)范來看事件循環(huán)

寫在最前

本次分享一下從HTML5PromiseA+規(guī)范來迅速理解一波事件循環(huán)中的microtask 與macrotask若厚。

歡迎關注我的博客连锯,不定期更新中——

JavaScript小眾系列開始更新啦

——何時完結不確定,寫多少看我會多少!這是已經更新的地址:

這個系列旨在對一些人們不常用遇到的知識點,以及可能常用到但不曾深入了解的部分做一個重新梳理,雖然可能有些部分看起來沒有什么用江兢,因為平時開發(fā)真的用不到!但個人認為糟粕也好精華也罷里面全部蘊藏著JS一些偏本質的東西或者說底層規(guī)范丁频,如果能適當避開舒適區(qū)來看這些小細節(jié)杉允,也許對自己也會有些幫助~文章更新在我的博客,歡迎不定期關注席里。

先來看段代碼

setTimeout(function() {
  console.log('setTimeout1');
    Promise.resolve().then(function() {
      console.log('promise1');
    }).then(function() {
      console.log('promise2');
    })
}, 0);
setTimeout(function() {
  console.log('setTimeout2');
    Promise.resolve().then(function() {
      console.log('promise3');
    }).then(function() {
      console.log('promise4');
    })
}, 0);

從這段代碼中我們發(fā)現里面有兩個定時器setTimeout叔磷,每個定時器中還嵌套了Promise。我相信熟悉microtask 與macrotask任務隊列的童鞋能很快的知曉答案奖磁,這個東西給我的感覺就是清者自清改基。

so 結果是什么?

/* 請在新版chrome中打印結果
    setTimeout1
    promise1
    promise2
    setTimeout2
    promise3
    promise4
*/

why?

不做解釋直接看下規(guī)范中怎么說的:

There must be at least one browsing context event loop per user agent, and at most one per unit of related similar-origin browsing contexts. An event loop has one or more task queues.

一個瀏覽器環(huán)境下只能有一個事件循環(huán)咖为,同時循環(huán)中是可以存在多個任務隊列的秕狰。
同時我們接著看規(guī)范中對event-loop執(zhí)行過程是如何規(guī)定的:

1.Let oldestTask be the oldest task on one of the event loop's task queues.

2.Set the event loop's currently running task to oldestTask.

3.Run oldestTask.

4.Set the event loop's currently running task back to null.

5.Remove oldestTask from its task queue.

6.Microtasks: Perform a microtask checkpoint.

7.Update the rendering

其中的task queues,就是之前提到的macrotask躁染,中文可以翻譯為宏任務鸣哀。顧名思義也就是正常的一些回調執(zhí)行,比如IO吞彤,setTimeout等我衬。簡單來說當事件循環(huán)開始后,會將task queues最先進棧的任務執(zhí)行饰恕,之后移出挠羔,進行到第六步,做microtask的檢測埋嵌。發(fā)現有microtask的任務那么會依照如下方式執(zhí)行:

While the event loop's microtask queue is not empty:

//當microtask隊列中還有任務時褥赊,按照下面執(zhí)行

1.Let oldestMicrotask be the oldest microtask on the event loop's microtask queue.

2.Set the event loop's currently running task to oldestMicrotask.

3.Run oldestMicrotask.

4.Set the event loop's currently running task back to null.

5.Remove oldestMicrotask from the microtask queue.

從這段規(guī)范可以看出,當執(zhí)行了一個macrotask后會有一個循環(huán)來檢查microtask隊列中是否還存在任務莉恼,如果有就執(zhí)行拌喉。這說明執(zhí)行了一個macrotask(宏任務)之后,會執(zhí)行所有注冊了的microtask(微任務)俐银。

一起看起來很正常對吧尿背?

那么如果微任務“嵌套”了呢?就像一開始作者給出的那段代碼一樣捶惜,promise調用了很多次.then方法田藐。這種情況文檔中有做出規(guī)定么?有的吱七。

If, while a compound microtask is running, the user agent is required to execute a compound microtask subtask to run a series of steps, the user agent must run the following steps:

1.Let parent be the event loop's currently running task (the currently running compound microtask).

2.Let subtask be a new task that consists of running the given series of steps. The task source of such a microtask is the microtask task source. This is a compound microtask subtask.

3.Set the event loop's currently running task to subtask.

4.Run subtask.

5.Set the event loop's currently running task back to parent.

簡單來說如果有“嵌套”的情況汽久,注冊的任務都是microtask,那么就會一股腦得全部執(zhí)行踊餐。

小結

通過上面對文檔的解讀我們可以知道以下幾件事:

  1. 一個運行環(huán)境有一個事件循環(huán)景醇。PS:有關web worker的概念作者也不太清楚,有興趣的童鞋可以查查
  2. 重點# 一個事件循環(huán)有多個任務隊列吝岭。目前來看是實現了兩個隊列

  3. 隊列分為macrotask宏任務隊列與microtask微任務隊列
  4. 回調的任務會被分配到macrotask與microtask中三痰,具體分配見下文。
  5. 執(zhí)行一個宏任務窜管,將已經注冊的所有微任務散劫,包括有“嵌套”的全部執(zhí)行。
  6. 執(zhí)行下一個宏任務幕帆,重復步驟5

那么還剩一件事情就是什么任務是macrotask获搏,什么是microtask?

image.png

這張圖來源一篇翻譯PromisA+的文章失乾,里面所提到的關于任務的分類常熙。

但是!我對于setImmediate與process.nextTick的行為持懷疑態(tài)度仗扬。理由最后說症概!不過在瀏覽器運行環(huán)境中我們不需要關系上面那兩種事件。

測試一下代碼

在本文一開始就提出早芭,這段代碼要在新版chrome中運行才會得到正確結果彼城。那么不在chrome中呢?

safari

舉個例子退个,別的作者不一一測試了募壕,這是safari中的結果。我們可以看到順序被打亂了语盈。so為什么我執(zhí)行了一樣的代碼結果卻不同舱馅?
個人認為若出現結果不同的情況是由于不同執(zhí)行環(huán)境(chrome, safari, node .etc)將回調需要執(zhí)行的任務所劃分到的任務隊列PromiseA+規(guī)范中所提到的任務隊列中的任務劃分準則執(zhí)行不一致導致的。也就是Promise可能被劃分到了macrotask中刀荒。有興趣深入了解的童鞋可以看下這篇tasks-microtasks-queues-and-schedules.

拋一個作者也解釋不清的問題

細心的童鞋可能發(fā)現我一直強調的js運行環(huán)境是瀏覽器下的事件循環(huán)情況代嗤。那么node中呢棘钞?

setTimeout(function() {
  console.log('setTimeout1');
    Promise.resolve().then(function() {
      console.log('promise1');
    }).then(function() {
      console.log('promise2');
    })
}, 0);
setTimeout(function() {
  console.log('setTimeout2');
    Promise.resolve().then(function() {
      console.log('promise3');
    }).then(function() {
      console.log('promise4');
    })
}, 0);

還是這段代碼,打印出來會不會有區(qū)別干毅?多打印幾次結果一樣么宜猜?為什么會這樣?

我只能理解到node通過libuv實現事件循環(huán)的方式與規(guī)范沒有關系硝逢,但具體為什么會打印出不同的效果姨拥。。求大神@我

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末渠鸽,一起剝皮案震驚了整個濱河市叫乌,隨后出現的幾起案子,更是在濱河造成了極大的恐慌徽缚,老刑警劉巖憨奸,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異猎拨,居然都是意外死亡膀藐,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門红省,熙熙樓的掌柜王于貴愁眉苦臉地迎上來额各,“玉大人,你說我怎么就攤上這事吧恃∠豪玻” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵痕寓,是天一觀的道長傲醉。 經常有香客問我,道長呻率,這世上最難降的妖魔是什么硬毕? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮礼仗,結果婚禮上吐咳,老公的妹妹穿的比我還像新娘。我一直安慰自己元践,他們只是感情好韭脊,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著单旁,像睡著了一般沪羔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上象浑,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天蔫饰,我揣著相機與錄音琅豆,去河邊找鬼。 笑死死嗦,一個胖子當著我的面吹牛趋距,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼浦译,長吁一口氣:“原來是場噩夢啊……” “哼郑原!你這毒婦竟也來了?” 一聲冷哼從身側響起坝冕,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后孩擂,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡箱熬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年类垦,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片城须。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚤认,死狀恐怖,靈堂內的尸體忽然破棺而出糕伐,到底是詐尸還是另有隱情砰琢,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布良瞧,位于F島的核電站陪汽,受9級特大地震影響,放射性物質發(fā)生泄漏褥蚯。R本人自食惡果不足惜挚冤,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赞庶。 院中可真熱鬧训挡,春花似錦、人聲如沸尘执。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽誊锭。三九已至表悬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丧靡,已是汗流浹背蟆沫。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工籽暇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饭庞。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓戒悠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舟山。 傳聞我的和親對象是個殘疾皇子绸狐,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容

  • 歡迎光臨我的博客拓跋的前端客棧,如果您發(fā)現我文章中存在錯誤累盗,請盡情向我吐槽寒矿,大家一起學習一起進步φ(>ω<*) 1...
    zhleven閱讀 5,465評論 5 12
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現若债,斷路器符相,智...
    卡卡羅2017閱讀 134,704評論 18 139
  • 春節(jié)臨近啊终,但我們卻感覺越來越沒有年味了。 如果不是看日歷傲须,根本連一點過節(jié)的氣氛都沒有蓝牲。這就是我們的現狀。 我在家里...
    語不惜閱讀 1,151評論 3 5
  • 我活在這個世上躏碳,無非是要明白一些道理搞旭,遇見些有趣的事情」矫啵——王小波 坐亦禪肄渗,行亦禪,坐也思量咬最,行也思量翎嫡,行坐...
    雲夢塵閱讀 394評論 0 1
  • 銳眼視點: 特斯拉挖走蘋果 Swift 創(chuàng)始人負責 Autopilot 開發(fā); Airmada 展示無人機地面站永乌;...
    銳眼看世界閱讀 341評論 0 0