需要理解同步與非同步我們必須從單執行緒說起
複製程式碼
什麼是單執行緒?單執行緒有什麼好處?單執行緒帶來了什麼問題?
js 本身是單執行緒的,單執行緒指的是同一時間段只能做同一件事情,也就是說兩段 js 程式碼不能同時執行。
js 是單執行緒的原因是為了避免 dom 渲染時被汙染
單執行緒會導致阻塞的問題,比如我們通常把 script 標籤放在 body 標籤之後,這也是為了解決單執行緒阻塞帶來的頁面短時間空白的問題。
單執行緒就意味著,所有任務需要排隊,前一個任務結束,才會執行後一個任務。如果前一個任務耗時很長,後一個任務就不得不一直等著。於是就有一個概念,任務佇列。如果排隊是因為計算量大,CPU忙不過來,倒也算了,但是很多時候CPU是閒著的,因為IO裝置(輸入輸出裝置)很慢(比如Ajax操作從網路讀取資料),不得不等著結果出來,再往下執行。JavaScript語言的設計者意識到,這時主執行緒完全可以不管IO裝置,掛起處於等待中的任務,先執行排在後面的任務。等到IO裝置返回了結果,再回過頭,把掛起的任務繼續執行下去。於是,所有任務可以分成兩種,一種是同步任務(synchronous),另一種是非同步任務(asynchronous)。
同步
同步指的是程式碼從上往下執行,只有上一個任務執行完之後才會執行下一個任務,在主執行緒中執行,並且形成一個執行棧。
同步程式碼:
```
console.log(1)
console.log(2)
console.log(3)
上面的程式碼會依次輸出 1 2 3
```
複製程式碼
非同步
非同步指的是程式碼不進入主執行緒的,而是進入一個任務佇列,只有在主執行緒中的程式碼執行完之後才會執行。
非同步所在的問題,會導致回撥地獄的出現,不利於程式碼的封裝,可讀性差。
非同步程式碼:
```
console.log(1)
setTimeout(function() {
console.log(2)
}, 0)
console.log(3)
上面的程式碼會輸出 1 3 2
得到這樣的結果是因為 setTimeout 函式是非同步的所以會將回撥函式放入非同步佇列中,等待主執行緒中的任務執行完之後,在執行回撥函式即使延遲時間為0。
```
複製程式碼
js 的執行機制也就是非同步的實現原理
非同步的實現原理主要是通過事件輪詢也就是Event Loop來實現的具體步驟如下:
1. 同步程式碼在主執行緒中從上往下開始執行,形成一個執行棧
2. 非同步程式碼發在非同步佇列中
3. 當主執行緒中的程式碼執行完之後,通過輪詢的方式來執行任務佇列中的程式碼
4. 主執行緒不斷重複上第三個步驟
複製程式碼