1. 程式人生 > >JS基礎知識(四)非同步和單執行緒

JS基礎知識(四)非同步和單執行緒

非同步和單執行緒

問題:

  1. 同步和非同步的區別是什麼?分別舉一個同步和非同步的例子

  2. 一個關於setTimeout的筆試題

    	console.log(1)
    	setTimeout(function() {
    		console.log(2)
    	},0)
    	console.log(3)
    	setTimeout(function() {
    		console.log(4)
    	},1000)
    	console.log(5)
  3. 前端使用非同步的場景有哪些

 

知識點:

JavaScript語言的一大特點就是單執行緒,也就是說,同一個時間只能做一件事。那麼,為什麼JavaScript不能有多個執行緒呢?這樣能提高效率啊。

JavaScript的單執行緒,與它的用途有關。作為瀏覽器指令碼語言,JavaScript的主要用途是與使用者互動,以及操作DOM。這決定了它只能是單執行緒,否則會帶來很複雜的同步問題。比如,假定JavaScript同時有兩個執行緒,一個執行緒在某個DOM節點上新增內容,另一個執行緒刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?

所以,為了避免複雜性,從一誕生,JavaScript就是單執行緒,這已經成了這門語言的核心特徵,將來也不會改變。

---摘自阮一峰es6入門

     1.什麼是非同步(對比同步)

          同步任務

:主執行緒排隊執行的任務,前一個執行完畢,後一個才能執行。

          非同步任務:不進入主執行緒,而進入任務佇列的任務,只有等主執行緒的任務結束以後,任務佇列開始通知主執行緒,請求執行任務,該任務才能進入主執行緒進行執行。

 

       主要區別:阻塞

       同步會阻塞後面的程式碼的執行,而非同步不會,非同步就自己管自己的。

      //非同步 
        console.log(100)
		setTimeout(function() {
			console.log(200)
		}, 1000)
		console.log(300)

		//100 300 200
		//對比同步的過程
		console.log(100)
		alert(200)
		console.log(300)

//100 200 300

 

什麼時候需要非同步呢?

     1.可能會發生等待的時候

     2.等待的過程中不會像alert一樣阻塞程式執行

     3.等待的狀態都需要非同步。

 

2.前端使用非同步的場景

     1.定時任務:setTimeout,setTimeInterval

     2.網路請求:ajax請求,動態<img>載入

     3. 事件繫結

//ajax
	    console.log('start')
		$.get('./test-test.json', function (data) {
			console.log(data)
		})
		console.log('end')
		
//start end data內容
	
//動態圖片載入	
		console.log('start')
		var img = document.createElement('img')
		img.onload = function () {
			console.log('loaded')
		}
		img.src= 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=300969297,3492652524&fm=58'
		console.log('end') 

//start end loaded
//事件繫結
		console.log('start')
		var btn1 = document.getElementById('btn1')
		btn1.addEventListener('click', function() {
			console.log('click')
		})
		console.log('end')

//start end click

 3.非同步和單執行緒

非同步:非同步場景會被拿出去,放在一邊。當程式都執行完了,再看非同步場景是否能執行了。

單執行緒:一次只能執行一個,一個個輪流下來。

      //非同步 
        console.log(100)
		setTimeout(function() {
			console.log(200)
		}, 1000)
		console.log(300)

		//100 300 200

 過程:

1.先執行第一行,列印100,

2.再執行setTimeout後,傳入setTimeout的函式會被暫存起來,不會立即執行(單執行緒的特點,不能同時幹兩件事)

3.執行最後一行,列印300

4.待所有程式執行完後,處於空閒狀態,會立馬看有沒有暫存起來的要執行的。

5.發現暫存起來的setTimeout中的函式無需等待時間,就立即來執行。

		//對比同步的過程
		console.log(100)
		alert(200)
		console.log(300)

//100 200 300

 過程:

1.先執行第一行,列印100

2.再遇到alert彈窗,阻塞,當點選完以後進行一步

3.列印300

//ajax
	    console.log('start')
		$.get('./test-test.json', function (data) {
			console.log(data)
		})
		console.log('end')
		
//start end data內容

 1.列印start

2.傳送請求,等待,暫存函式,類似把他封印起來,

3.列印end

4.執行完了看看有沒有什麼是在等待的,解封的時候就是看他什麼時候有返回。

//事件繫結
		console.log('start')
		var btn1 = document.getElementById('btn1')
		btn1.addEventListener('click', function() {
			console.log('click')
		})
		console.log('end')

//start end click

1.列印start

2.繫結事件,暫存非同步的函式,把他封印起來

3.列印end

4.當點選的時候會解封,然後執行列印click

 

onclick執行多次,事件繫結的特點可以多次執行,執行機制與其他相同。

 

解答:

  1. 同步和非同步的區別是什麼?分別舉一個同步和非同步的例子
    同步會阻塞,非同步不會阻塞,同步alert,非同步setTimeout

  2. 一個關於setTimeout的筆試題
    寫出結果:

    	console.log(1)
    	setTimeout(function() {
    		console.log(2)
    	},0)
    	console.log(3)
    	setTimeout(function() {
    		console.log(4)
    	},1000)
    	console.log(5)

    // 1 3 5 2 4 
     

    for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, 1000);
    }

    結果:五個5
    因為for的同步優於setTimeout非同步,然後結果就是for執行完了以後,五個setTimeout在等待著,然後同時輸出五個i,因為i是var是全域性作用域,此時的i已經變成了5.所以輸出的都是5.

  3. 前端使用非同步的場景有哪些
    1.定時任務:setTimeout, setInterval
    2.網路請求:ajax請求,動態<img>載入
    3.事件繫結