您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何理解JS的同步異步編程和EventLoop底層機制”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何理解JS的同步異步編程和EventLoop底層機制”吧!
1)JS是單線程的,大部分代碼都是同步編程。
2)JS中利用瀏覽器的多線程機制,基于單線程的EventLoop(事件循環機制)實現出異步的效果。
1)微任務 (microtask):優先級高,并且可以插隊,不是先定義先執行。包括:promise.then,async/await [generator],requestAnimationFrame,observer,MutationObserver,setImmediate。
2)宏任務 (macrotask):優先級低,先定義的先執行。包括:ajax,setTimeout,setInterval,事件綁定,postMessage,MessageChannel(用于消息通訊)。
+先找微任務隊列,如果微任務隊列中有,先從微任務隊列中,一般按照存放順序獲取并且去執行。
+如果微任務隊列中沒有,則再去宏任務隊列中查找,在宏任務隊列中,一般是按照誰先到達執行的條件,就先把誰拿出來執行。
? 面試題1:
console.log('1') // 1 async function async1() { console.log('2') // 2 await setTimeout(() => { console.log('3') // 8 }, 0) console.log('4') // 5 } setTimeout(() => { console.log('5') // 7 }, 0) async1() new Promise(function (resolve) { console.log('6') // 3 resolve() }).then(function () { console.log('7') // 6 }) console.log('8') // 4 // 結果:1 2 6 8 4 7 5 3
? 面試題2:
async function async1() { console.log('async1 start'); // 2 await async2(); console.log('async1 end'); // 6 } async function async2() { console.log('async2'); // 3 } console.log('script start'); // 1 setTimeout(function () { console.log('setTimeout'); // 8 }, 0) async1(); new Promise(function (resolve) { console.log('promise1'); // 4 resolve(); }).then(function () { console.log('promise2'); // 7 }); console.log('script end'); // 5 //結果: script start async1 start async2 promise1 script end async1 end promise2 setTimeout
? 面試題3:
console.log(1); // 1 setTimeout(() => { console.log(2); // 6 Promise.resolve().then(data => { console.log(3); // 7 }); }); new Promise((resolve) => { resolve() console.log(4) // 2 }).then(() => { console.log(5); // 4 setTimeout(() => { console.log(6); // 8 }); }).then(() => console.log(7)) // 5 console.log(8); // 3 // 結果:1, 4, 8, 5, 7, 2, 3, 6 1, 4, 8 是同步 5, 7 是微任務 2 宏任務 3 微任務 6 宏任務
* 核心答案 | 基礎知識要夯實
1) 進程代表的是一個程序(瀏覽器開一個頁卡 (Tab頁) 就是一個進程);
2) 線程是用來處理處理進程中的具體事物的,如果一個程序中需要同時做好多事情,就需要開辟好多線程;
3) 一個線程同時只能做一件事情;
官方的說法
1) 進程是cpu資源分配的最小單位(是能擁有資源和獨立運行的最小單位)。
2) 線程是cpu調度的最小單位(線程是建立在進程的基礎上的一次程序運行單位,一個進程中可以有多個線程)。
* 核心答案 | 基礎知識要夯實
1) 瀏覽器是多進程的;
2) 瀏覽器之所以能夠運行,是因為系統給它的進程分配了資源(cpu、內存);
3) 簡單點理解,每打開一個Tab頁,就相當于創建了一個獨立的瀏覽器進程;
那么接下來看看它都包含了哪些線程(列舉一些主要常駐線程)
1) 負責渲染瀏覽器界面,解析HTML,CSS,構建DOM樹和RenderObject樹,布局和繪制等。
2) 當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行。
3) 注意,GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(相當于被凍結了),GUI更新會被保存在一個隊列中等到JS引擎空閑時立即被執行。
也稱為JS內核,負責處理Javascript腳本程序。(例如V8引擎)
1) JS引擎線程負責解析Javascript腳本,運行代碼。
2) JS引擎一直等待著任務隊列中任務的到來,然后加以處理,一個Tab頁(renderer進程)中無論什么時候都只有一個JS線程在運行JS程序。
3) 同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞。
* 核心答案 | 基礎知識要夯實
JS是單線程的:瀏覽器只分配一個線程用來渲染JS代碼。
1、JS中的代碼大部分都是“同步編程”:上面的任務沒有處理完成,下面的任務是無法處理的。
2?但是JS中利用瀏覽器的多線程機制,可以規劃出“異步編程”效果。
定時器
ajax/Fetch/跨域 (HTTP網絡請求)
事件綁定
Promise中有也有異步編程
Generator / yield
async / await
計算程序執行的時間(預估)
1)運行監控 console.time/timeEnd(受當前電腦運行環境的影響)
2)大O表示法(提前預估)
console.time('AAA'); for (let i = 0; i < 99999999; i++) {} console.timeEnd('AAA');
真實項目中應該避免死循環 (重要)
while (true) {} console.log('OK'); // 不執行:上述的死循環一直占用這“JS渲染線程”,線程空閑不下來,就處理不了其他的事情
1)設置定時器任務是同步的
2)“間隔interval這么長時間,執行定時器綁定的函數” 這個任務是異步的
3)遇到異步任務,瀏覽器不會等待它執行完,則繼續渲染下面的代碼;當等到下面代碼運行完,時間也到達了執行的條件,才會把異步任務執行;
setTimeout(() => { console.log("OK"); //2 }, 1000); console.log('NO'); //1
interval設置為零也不是立即執行,而是瀏覽器都有“最快反應時間(谷歌:5~6ms IE:13~17ms)”,設置為零,最快也需要等到5~6ms左右
setTimeout(() => { console.log('OK'); //2 }, 0); console.log('NO'); //1
setTimeout(() => { console.log(1); }, 20); console.log(2); setTimeout(() => { console.log(3); }, 10); console.log(4); console.time('AA'); for (let i = 0; i < 90000000; i++) { // do soming } console.timeEnd('AA'); //=>AA: 79ms 左右 console.log(5); setTimeout(() => { console.log(6); }, 8); console.log(7); setTimeout(() => { console.log(8); }, 15); console.log(9); // 結果:2,4,5,7,9,3,1,6,8
畫圖分析:( 有圖有真相 )
執行順序:同步任務 —> 微任務 —> 宏任務 (微任務、宏任務在EventQueue)
細節點
當棧中的“同步任務”或者其它任務沒有執行完之前,JS渲染線程不會空閑下來,些時哪怕定時器已經到達指定時間,也不會執行的。 “JS是單線程的,一次只能做一件事情” => 定時器設定的等待時間是最快觸發執行的時間,很多時候,到時間不一定會執行,只有JS渲染線程空閑下來才會執行。
感謝各位的閱讀,以上就是“如何理解JS的同步異步編程和EventLoop底層機制”的內容了,經過本文的學習后,相信大家對如何理解JS的同步異步編程和EventLoop底層機制這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。