【知識點】JS運行機制

爲何js是單線程的

咱們用反證法證實這個問題,假設js是多線程的。es6

場景描述:promise

假設如今有2個進程:process1,process2。因爲是js是多進程的,因此這兩個進程同時對一個dom進行操做。瀏覽器

process1 刪除了該dom。bash

process2 編輯了該dom。多線程

同時下達2個矛盾的命令,瀏覽器究竟該如何執行呢?dom

顯然做爲瀏覽器腳本語言,就決定了js只能是單線程的,也稱爲主線程。異步

JS爲何須要異步

一樣用反證法,假設js是同步的。oop

場景描述:ui

若是JS中不存在異步,只能自上而下執行,若是上一行解析時間很長,那麼下面的代碼就會被阻塞。spa

對於用戶而言,阻塞就意味着"卡死",這樣就致使了不好的用戶體驗。

JS單線程又是如何實現異步的呢?

經過的事件循環(event loop)實現異步。

什麼是事件循環

js任務分類:

  • macro-task(宏任務):包括總體代碼script,setTimeout,setInterval
  • micro-task(微任務):Promise.then(),MutationObserver。

event loop:

  1. 執行一個宏任務,過程當中若是遇到微任務,就將其放到微任務的【事件隊列】裏
  2. 當前宏任務執行完成後,會查看微任務的【事件隊列】
  3. 若是有微任務,將裏面所有的微任務依次執行完
  4. 若是沒有微任務,跳到第1步。

event loop圖解

總結:

涉及概念: 運行棧(同步任務)、任務隊列(異步任務)、event loop

不斷去任務隊列中取異步任務的過程叫event loop

何時會開啓異步任務:setTimeout 和 setIntveral、DOM事件、es6中的promise等

語句放入異步任務隊列時機:遇到異步任務不會馬上把代碼放到任務隊列中,會等到觸發時(settimeout 時間到了 dom事件觸發了)在放到任務隊列中:

var a= 1;
setTimeout(a, 1000);
setTimeout(b, 500);
//b先被放到異步隊列
複製代碼

例子

例子1

// 1 3 2
console.log(1);      //同步任務
setTimeout(function(){      //異步任務
	console.log(2);
},0)
console.log(3);      //同步任務
複製代碼

例子2

// 1
console.log(1);      //同步任務
while(true){      //同步任務
			
}
console.log(2);      //同步任務
複製代碼

例子3

// 1
console.log(1);      //同步任務
setTimeout(function(){      //異步任務
	console.log(2);
},0)
while(true){      //同步任務
			
}
複製代碼

例子4

//4 4 4 4
for(var i=0;i<4;i++){            //同步任務
	setTimeout(function(){      //異步任務
		console.log(i);
	},1000)
}
複製代碼

例子5

//2 4 3 1
setTimeout(function(){
    console.log('1')
});
 
new Promise(function(resolve){
    console.log('2');
            resolve();
}).then(function(){
    console.log('3')
});
 
console.log('4');
複製代碼
相關文章
相關標籤/搜索