非同步模式(Asynchronous)

泗洪雙溝 發表於 2020-11-22

概念:
不會去等待這個任務的結束才開始下一個任務,開啟過後就立即往後執行下一個任務,後續邏輯一般會通過回撥函式的方式定義。單執行緒的JavaScript語言需要通過赭紅模式去同時處理大量的耗時任務。對於開發者來說難點是程式碼的執行順序混亂
講解

console.log('gobal begin')
setTimeout(function timer1(){
	console.log('timer1 invoke')
},1800)
setTimeout(function timer2(){
	console.log('timer2 invoke')
	setTimeout(function inner(){
		console.log('inner invoke')
	},1000)
},1000)
console.log('global end')

1、js執行引擎會把整體的程式碼全部載入進來
2、然後在呼叫棧(Call stack)當中壓入一個匿名(anonymous)的全域性呼叫,這個匿名的呼叫可以理解為把全部的程式碼放入到一個匿名的函式當中去執行,然後去逐行執行
3、呼叫棧中依次壓入上述程式碼去執行,呼叫棧中:
(anonymous) 逐行執行
console.log(‘global begin’) 執行 彈出
setTimeout(timer1) 執行
為timer1開啟一個倒數計時器 1.8stimer1放到一邊,這個倒數計時器是單獨工作不會受js單執行緒影響
彈出
setTimeout(timer2) 執行
為timer2開啟一個倒數計時器 1stimer2放到一邊
彈出
console.log(‘global end’) 執行 彈出
此時呼叫棧被清空 event loop開始發揮作用
event loop:負責監聽呼叫棧與訊息佇列,呼叫棧所有任務都結束了,event loop 會從訊息佇列中取出第一個回撥函式壓入到呼叫棧,此時訊息佇列為空,執行暫停下來了,等倒數計時結束後,timer2倒數計時先結束 放入到訊息佇列的第1位,timer1進入訊息佇列第2位,事件迴圈監聽到訊息佇列變化
開啟新一輪的呼叫棧
timer2壓入到呼叫棧 執行
setTimeout(inner) 執行
console.log(‘timer2 invoke’) 執行 彈出
為inner開啟一個倒數計時器 1sinner放到一邊
彈出
timer1 執行
console.log(‘timer1 invoke’) 執行 彈出
彈出
開啟新一輪的呼叫棧
inner壓入到呼叫棧 執行
console.log(‘inner invoke’) 執行 彈出
彈出
結束

注意:js時單執行緒,瀏覽器不是單執行緒。js呼叫的某些內部的api並不是單執行緒的
我們說的同步還是非同步不是指寫程式碼的方式,而是執行環境提供的API是以同步或非同步模式的方式工作