秒懂JS中的同步/異步編程是什麼

1. 進程(process)/線程(thread)

進程process: 電腦端安裝不少的應用軟件,每當運行一個應用程序,至關於開闢一個進程(而對於瀏覽器來講,每新建一個頁卡訪問一個頁面,都是新開闢一個進程)web

  • 任務管理器能夠查看進程

線程thread: 每個進程中可能還會同時作不少事情,若是程序中須要同時處理不少事情,則須要開闢多個線程(一個線程同時只能作一個事情)編程

=> 一個進程中,會包含0~多個線程promise

理解:瀏覽器

  • 每個飯店是一個進程
  • 飯店裏面每個點餐的服務員就是一個線程

2. JS是單線程的線程

瀏覽器是‘多線程’的,可是JS渲染或者頁面渲染是‘單線程’的多線程

2.1 瀏覽器中線程的分類

  • GUI渲染線程(渲染和繪製頁面)
  • JS引擎線程(運行和渲染JS代碼)
  • 事件管控和觸發線程
  • 定時器管控和觸發線程
  • 異步HTTP請求線程
  • ...

2.2 JS代碼的渲染是單線程的

瀏覽器是多線程的(打開一個頁面之後,瀏覽器至少要分配好幾個線程同時去處理事情),可是瀏覽器只會分配出一個線程去渲染代碼(GUI渲染線程),因此說JS是單線程的:‘在JS代碼執行過程當中,一次只能處理一個事情’異步

3. 同步與異步

  • 同步編程【單線程】:任務是一次執行,上面的任務沒有執行完成,下面的任務是不能去操做的
  • 異步編程【多線程】:同時能夠處理不少事情,可是JS中的異步編程是利用瀏覽器的相關機制構造出來的異步效果

通俗的理解:好比咱們在食堂打飯這個場景: 咱們在排隊打飯,可是當排到B打飯的時候,他的王者榮耀遊戲尚未打完(吃飯不積極,思想...😅)async

  • 此時同步編程思想處理的方式就是:咱們你們都等B打完遊戲,只要B不打飯,後面的也不能打飯(B不會就是食堂老闆的兒子吧,這麼多人等他打遊戲🤔)
  • 可是異步編程思想處理方式是這樣的:無論你的後臺有多大,騰不出手,就去旁邊的任務隊列等着去,等咱們你們都打完飯,你的遊戲也打完了,再來打飯(這你還怎麼猖狂😂)
同步編程
同步編程
異步編程
異步編程

3.1 常見的異步代碼

  • 定時器:設置定時器是同步(當即設置),異步指的是間隔多久後執行指定的函數
  • 事件綁定(監聽)
  • AJAX的異步請求
  • promise/async/await

4 定時器

  • setTimeout
  • setInterval

4.1 定時器的返回值

返回值:是一個數字,表明當前是第幾個定時器編輯器

  • 咱們後期能夠基於clearTimeout / clearInterval 清除定時器
  • 手動把timer賦值爲null,後期基於它的值驗證是否存在定時器

4.2 瀏覽器的最小反應時間

  • 定時器是異步的:遇到定時器先不執行,先去執行其餘事情,等到全部事情作完再看那個定時器到達時間而後能夠立馬執行;
  • 定時器的等待時間即便設置爲零,也不是當即執行,瀏覽器有一個最小的等待時間(谷歌5~6MS IE瀏覽器10~13MS
  • 最小反應時間:在滾動相同的距離下,事件被觸發多少次,取決於滾動所用的時間(速度)來決定的,瀏覽器有最小的反應時間,假設是5MS,總體運動時間100MS,這段時間內,瀏覽器可以識別出來的次數是100/5 = 20次。同理,若是咱們運動1000MS,那麼識別觸發的次數就是1000/5=200次

4.3 從定時器的執行過程理解它的異步的

  • 把代碼拿到棧中執行,當遇到異步代碼定時器的時候,會當即把定時器拿到任務隊列中去等待必定時間
  • 當把主線程的全部代碼執行完畢以後,去任務隊列中查看哪一個定時器到達時間,把到達時間的定時器拿到棧中執行(這種操做是異步)

=> 遇到定時器不是不處理,而是把它放在任務隊列,等到主線程空閒下來,再去任務隊列查看,這種操做是異步。中途定時器到達時間了,可是主線程並無到達時間,此時也不會當即執行定時器,必須等到主線程空閒下來。異步編程

4.4 下面是關於定時器的對異步代碼的理解,配有圖片和註釋的說明👇

4.4.1 題目一

let n = 0;
setTimeout(() => {  n++;  console.log(n); //=> 3 (2) }, 1000); //一秒鐘以後執行 n += 2; console.log(n); //=> 2 (1) 複製代碼
題目一
題目一

4.4.2 題目二

let n = 0;
setTimeout(() => {  n++;  console.log(n); //=> 3 (2) },0); //寫零也不是當即執行,而是有一個最小的等待時間:10ms左右 n += 2; console.log(n); //=> 2 (1) 複製代碼

4.4.3 題目三

let n = 10;
setTimeout(() => {  n++;  console.log(n); //=>11(3) }, 0); console.log(n); //=>10(1) for(let i = 0;i < 99999999; i++){} console.log(n); //=>10(2) 複製代碼
題目三
題目三

4.4.4 題目四

time / timeEnd:獲取他們中間代碼執行所須要的時間(這個時間須要受到電腦配置、和當前電腦運行的環境等多方面因素影響),時間只做爲參考函數

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); 複製代碼
題目四
題目四

4.4.5 題目五

console.log(1); //=>1(1)
setTimeout(function () {  console.log(2); }, 20); console.log(3); //=>3(2) for (let i = 0; i > -1; i++) {} //=>死循環,GUI線程啥都作不了,一直在這加載(其它什麼事情都幹不了) console.log(4); setTimeout(function () {  console.log(5); }, 10); console.log(6); 複製代碼

5. 事件循環 Event Loop

定義:JS是單線程的,由於瀏覽器只分配一個線程自上而下加載代碼。因此JS中大部分任務都是同步任務。可是必定也有異步任務,定時器、事件綁定等這些都屬於異步任務。

而瀏覽器處理JS中的異步任務是:在JS代碼自上而下執行的時候,代碼進棧執行,執行完出棧,在這反反覆覆進行的過程當中。當遇到定時器等異步任務的時候,會把當前任務放在等待任務隊列(Event Queue)中存起來,而且存起來以後不會影響下面代碼的執行,主線程會繼續執行。當 把下面的同步任務執行完成以後,主線程空閒下來了會去等待隊列找哪個任務到達指定的時間點,就拿到主線程中去執行。執行完以後再去等待隊列中查看...

相關文章
相關標籤/搜索