自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JS基礎(chǔ)進(jìn)階- 同步異步編程和EventLoop底層機(jī)制

開(kāi)發(fā) 前端
本篇通過(guò)幾道面試題,和大家聊聊關(guān)于JS基礎(chǔ)進(jìn)階之同步異步編程和EventLoop底層機(jī)制,希望能夠?qū)δ阌兴鶐椭?/div>

[[389054]]

簡(jiǎn)短的概括:

  • JS中的單線程異步編程
  • EventLoop 事件循環(huán)機(jī)制
  • 宏任務(wù) macrotask [ˈmækroʊ]
  • 微任務(wù) microtask [ˈmaɪkroʊ]
  • JS中的同步異步編程

1、JS是單線程的,怎么達(dá)到異步編程:

1)JS是單線程的,大部分代碼都是同步編程。

2)JS中利用瀏覽器的多線程機(jī)制,基于單線程的EventLoop(事件循環(huán)機(jī)制)實(shí)現(xiàn)出異步的效果。

2、event loop (微任務(wù)與宏任務(wù)):

1)微任務(wù) (microtask):優(yōu)先級(jí)高,并且可以插隊(duì),不是先定義先執(zhí)行。包括:promise.then,async/await [generator],requestAnimationFrame,observer,MutationObserver,setImmediate。

2)宏任務(wù) (macrotask):優(yōu)先級(jí)低,先定義的先執(zhí)行。包括:ajax,setTimeout,setInterval,事件綁定,postMessage,MessageChannel(用于消息通訊)。

3、根據(jù)事件循環(huán)機(jī)制,重新梳理一下流程:

+先找微任務(wù)隊(duì)列,如果微任務(wù)隊(duì)列中有,先從微任務(wù)隊(duì)列中,一般按照存放順序獲取并且去執(zhí)行。

+如果微任務(wù)隊(duì)列中沒(méi)有,則再去宏任務(wù)隊(duì)列中查找,在宏任務(wù)隊(duì)列中,一般是按照誰(shuí)先到達(dá)執(zhí)行的條件,就先把誰(shuí)拿出來(lái)執(zhí)行。

??济嬖囶}:EventLoop事件循環(huán)

🌰 面試題1:

  1. console.log('1') // 1 
  2.  
  3. async function async1() { 
  4.   console.log('2') // 2 
  5.   await setTimeout(() => { 
  6.     console.log('3') // 8 
  7.   }, 0) 
  8.   console.log('4') // 5 
  9.  
  10. setTimeout(() => { 
  11.   console.log('5') // 7 
  12. }, 0) 
  13.  
  14. async1() 
  15.  
  16. new Promise(function (resolve) { 
  17.   console.log('6') // 3 
  18.   resolve() 
  19. }).then(function () { 
  20.   console.log('7') // 6 
  21. }) 
  22.  
  23. console.log('8') // 4 
  24. // 結(jié)果:1 2 6 8 4 7 5 3 

🌰 面試題2:

  1. async function async1() { 
  2.     console.log('async1 start'); // 2 
  3.     await async2(); 
  4.     console.log('async1 end'); // 6 
  5. async function async2() { 
  6.     console.log('async2'); // 3 
  7. console.log('script start'); // 1 
  8. setTimeout(function () { 
  9.     console.log('setTimeout'); // 8 
  10. }, 0) 
  11. async1(); 
  12. new Promise(function (resolve) { 
  13.     console.log('promise1'); // 4 
  14.     resolve(); 
  15. }).then(function () { 
  16.     console.log('promise2'); // 7 
  17. }); 
  18. console.log('script end'); // 5 
  19. //結(jié)果: 
  20. script start 
  21. async1 start 
  22. async2 
  23. promise1 
  24. script end 
  25. async1 end 
  26. promise2 
  27. setTimeout 

🌰 面試題3:

  1. console.log(1); // 1 
  2. setTimeout(() => { 
  3.   console.log(2); // 6 
  4.   Promise.resolve().then(data => { 
  5.      console.log(3); // 7 
  6.   }); 
  7. }); 
  8. new Promise((resolve) => { 
  9.   resolve() 
  10.   console.log(4) // 2 
  11. }).then(() => { 
  12.   console.log(5); // 4 
  13.   setTimeout(() => { 
  14.     console.log(6); // 8 
  15.   }); 
  16. }).then(() => console.log(7)) // 5 
  17. console.log(8); // 3 
  18.  
  19. // 結(jié)果:1, 4, 8, 5, 7, 2, 3, 6 
  20. 1, 4, 8 是同步  5, 7  是微任務(wù)  2 宏任務(wù) 3 微任務(wù)  6 宏任務(wù) 

進(jìn)程/線程

* 核心答案 | 基礎(chǔ)知識(shí)要夯實(shí)

1) 進(jìn)程代表的是一個(gè)程序(瀏覽器開(kāi)一個(gè)頁(yè)卡 (Tab頁(yè)) 就是一個(gè)進(jìn)程);

2) 線程是用來(lái)處理處理進(jìn)程中的具體事物的,如果一個(gè)程序中需要同時(shí)做好多事情,就需要開(kāi)辟好多線程;

3) 一個(gè)線程同時(shí)只能做一件事情;

  • 官方的說(shuō)法
  • 1) 進(jìn)程是cpu資源分配的最小單位(是能擁有資源和獨(dú)立運(yùn)行的最小單位)。
  • 2) 線程是cpu調(diào)度的最小單位(線程是建立在進(jìn)程的基礎(chǔ)上的一次程序運(yùn)行單位,一個(gè)進(jìn)程中可以有多個(gè)線程)。

瀏覽器是多線程的

* 核心答案 | 基礎(chǔ)知識(shí)要夯實(shí)

1) 瀏覽器是多進(jìn)程的;

2) 瀏覽器之所以能夠運(yùn)行,是因?yàn)橄到y(tǒng)給它的進(jìn)程分配了資源(cpu、內(nèi)存);

3) 簡(jiǎn)單點(diǎn)理解,每打開(kāi)一個(gè)Tab頁(yè),就相當(dāng)于創(chuàng)建了一個(gè)獨(dú)立的瀏覽器進(jìn)程;


那么接下來(lái)看看它都包含了哪些線程(列舉一些主要常駐線程)

GUI渲染線程

1) 負(fù)責(zé)渲染瀏覽器界面,解析HTML,CSS,構(gòu)建DOM樹(shù)和RenderObject樹(shù),布局和繪制等。

2) 當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí),該線程就會(huì)執(zhí)行。

3) 注意,GUI渲染線程與JS引擎線程是互斥的,當(dāng)JS引擎執(zhí)行時(shí)GUI線程會(huì)被掛起(相當(dāng)于被凍結(jié)了),GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JS引擎空閑時(shí)立即被執(zhí)行。

JS引擎線程

也稱(chēng)為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序。(例如V8引擎)

1) JS引擎線程負(fù)責(zé)解析Javascript腳本,運(yùn)行代碼。

2) JS引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來(lái),然后加以處理,一個(gè)Tab頁(yè)(renderer進(jìn)程)中無(wú)論什么時(shí)候都只有一個(gè)JS線程在運(yùn)行JS程序。

3) 同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執(zhí)行的時(shí)間過(guò)長(zhǎng),這樣就會(huì)造成頁(yè)面的渲染不連貫,導(dǎo)致頁(yè)面渲染加載阻塞。

JS中的單線程異步編程

* 核心答案 | 基礎(chǔ)知識(shí)要夯實(shí)

JS是單線程的:瀏覽器只分配一個(gè)線程用來(lái)渲染JS代碼。

1、JS中的代碼大部分都是“同步編程”:上面的任務(wù)沒(méi)有處理完成,下面的任務(wù)是無(wú)法處理的。

2、但是JS中利用瀏覽器的多線程機(jī)制,可以規(guī)劃出“異步編程”效果。

  • 定時(shí)器
  • ajax/Fetch/跨域 (HTTP網(wǎng)絡(luò)請(qǐng)求)
  • 事件綁定
  • Promise中有也有異步編程
  • Generator / yield
  • async / await

計(jì)算程序執(zhí)行的時(shí)間(預(yù)估)

1)運(yùn)行監(jiān)控 console.time/timeEnd(受當(dāng)前電腦運(yùn)行環(huán)境的影響)

2)大O表示法(提前預(yù)估)

  1. console.time('AAA');  
  2. for (let i = 0; i < 99999999; i++) {}  
  3. console.timeEnd('AAA'); 

真實(shí)項(xiàng)目中應(yīng)該避免死循環(huán) (重要)

  1. while (true) {} 
  2. console.log('OK'); // 不執(zhí)行:上述的死循環(huán)一直占用這“JS渲染線程”,線程空閑不下來(lái),就處理不了其他的事情  

定時(shí)器的異步編程

1)設(shè)置定時(shí)器任務(wù)是同步的

2)“間隔interval這么長(zhǎng)時(shí)間,執(zhí)行定時(shí)器綁定的函數(shù)” 這個(gè)任務(wù)是異步的

3)遇到異步任務(wù),瀏覽器不會(huì)等待它執(zhí)行完,則繼續(xù)渲染下面的代碼;當(dāng)?shù)鹊较旅娲a運(yùn)行完,時(shí)間也到達(dá)了執(zhí)行的條件,才會(huì)把異步任務(wù)執(zhí)行;

  1. setTimeout(() => { 
  2.     console.log("OK"); //2 
  3. }, 1000); 
  4. console.log('NO'); //1 

interval設(shè)置為零也不是立即執(zhí)行,而是瀏覽器都有“最快反應(yīng)時(shí)間(谷歌:5~6ms IE:13~17ms)”,設(shè)置為零,最快也需要等到5~6ms左右

  1. setTimeout(() => { 
  2.     console.log('OK'); //2 
  3. }, 0); 
  4. console.log('NO'); //1 

🌰 異步編程例子一:

  1. setTimeout(() => { 
  2.     console.log(1); 
  3. }, 20); 
  4. console.log(2); 
  5. setTimeout(() => { 
  6.     console.log(3); 
  7. }, 10); 
  8. console.log(4); 
  9. console.time('AA'); 
  10. for (let i = 0; i < 90000000; i++) { 
  11.     // do soming 
  12. console.timeEnd('AA'); //=>AA: 79ms 左右 
  13. console.log(5); 
  14. setTimeout(() => { 
  15.     console.log(6); 
  16. }, 8); 
  17. console.log(7); 
  18. setTimeout(() => { 
  19.     console.log(8); 
  20. }, 15); 
  21. console.log(9); 
  22. // 結(jié)果:2,4,5,7,9,3,1,6,8 

畫(huà)圖分析:( 有圖有真相 )


執(zhí)行順序:同步任務(wù) —> 微任務(wù) —> 宏任務(wù) (微任務(wù)、宏任務(wù)在EventQueue)

  • 細(xì)節(jié)點(diǎn)
  • 當(dāng)棧中的“同步任務(wù)”或者其它任務(wù)沒(méi)有執(zhí)行完之前,JS渲染線程不會(huì)空閑下來(lái),些時(shí)哪怕定時(shí)器已經(jīng)到達(dá)指定時(shí)間,也不會(huì)執(zhí)行的。 “JS是單線程的,一次只能做一件事情” => 定時(shí)器設(shè)定的等待時(shí)間是最快觸發(fā)執(zhí)行的時(shí)間,很多時(shí)候,到時(shí)間不一定會(huì)執(zhí)行,只有JS渲染線程空閑下來(lái)才會(huì)執(zhí)行。

 

責(zé)任編輯:姜華 來(lái)源: 前端學(xué)苑
相關(guān)推薦

2012-07-27 10:02:39

C#

2019-05-27 14:40:43

Java同步機(jī)制多線程編程

2021-12-08 07:55:41

EventLoop瀏覽器事件

2021-09-06 13:12:05

前端JavaScript編程

2020-09-21 14:35:20

VuenextTick前端

2020-03-27 10:08:10

JS異步 I

2012-03-01 20:32:29

iOS

2013-03-08 09:33:25

JavaScript同步異步

2012-06-14 13:40:04

JavaScript

2019-01-17 10:58:52

JS異步編程前端

2012-06-14 13:55:39

JavaScript

2021-08-16 15:49:31

開(kāi)發(fā)框架單線程異步

2015-07-03 10:12:04

編程同步非阻塞

2018-01-30 18:15:12

Python網(wǎng)絡(luò)爬蟲(chóng)gevent

2023-09-07 08:15:58

場(chǎng)景同步異步

2019-07-23 11:01:57

Python同步異步

2010-01-15 09:15:09

Scala Actor并發(fā)

2013-04-01 15:38:54

異步編程異步編程模型

2019-02-27 16:00:48

JS原型原型鏈對(duì)象

2021-09-26 05:06:46

JS垃圾內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)