1. 程式人生 > >關於javascript單執行緒及非同步的學習筆記

關於javascript單執行緒及非同步的學習筆記

JavaScript不像其他語言比如Java一樣多執行緒,就不必去考慮執行緒同步的問題。

JavaScript是瀏覽器用來與使用者進行互動、進行DOM操作的,這也使得了它必須是單執行緒這一特性。比如你去修改一個元素的DOM,同時又去刪除這個元素,那麼瀏覽器應該聽誰的?

在JavaScript中任務有兩種,一種是同步任務,一種是非同步任務。

同步任務:各個任務按照文件定義的順序一一推入"執行棧"中,當前一個任務執行完畢,才會開始執行下一個任務。

非同步任務:各個任務推入"任務佇列"中,只有在當前的所有同步任務執行完畢,才會將佇列中的任務"出隊"執行。(注:這裡的非同步任務並不一定是按照文件定義的順序推入佇列中)

//只有使用者觸發點選事件才會被推入佇列中(如果點選時間小於定時器指定的時間,則先於定時器推入,否則反之)
document.querySelector("#box").onclick = function(){
  console.log("click");
};
//第一個推入佇列中
setTimeout(function(){
  console.log("1");
},0);
//第三個推入佇列中
setTimeout(function(){
 console.log("2");
},1000);
//第二個推入佇列中
setTimeout(function(){
  console.log("3");
},
0);

當然了,這時候你會疑惑"任務佇列是什麼?非同步任務通常包括哪些?"

任務佇列(event loop):你可理解為用於存放事件的佇列,當執行一個非同步任務時,就相當於執行任務的回撥函式。

通常io(ajax獲取伺服器資料)、使用者/瀏覽器自執行事件(onclick、onload、onkeyup等等)以及定時器(setTimeout、setInterval)都可以算作非同步操作

我所知道的有這些,如果有其它的事件是非同步的,歡迎大大補充。


先來看一段程式碼來理解一下

console.log("1");

setTimeout(function(){
	console.log("2");
},1000); console.log("3"); setTimeout(function(){ console.log("4"); },0);

輸出結果: 1->3->4->2.

分析

1. 兩個console.log()都是同步,按照文件的順序將它們推入"執行棧"中。

2. 執行棧中的同步任務執行完畢。

3. 將兩個非同步任務(定時器)按照第二個引數(延遲執行的時間)順序推入"任務佇列"中。

4. 一一執行非同步任務。


那麼在來看你這段程式碼。

//同步code1
var t = true;

//非同步code2
window.setTimeout(function (){
    t = false;
},1000);

//同步code2
while (t){}

//同步code3
alert('end');

分析

1. 先執行同步code1->同步code2。

2. 此時while(true){},進入死迴圈,以後的程式碼都不會執行。