JS基礎知識(四)非同步和單執行緒
非同步和單執行緒
問題:
-
同步和非同步的區別是什麼?分別舉一個同步和非同步的例子
-
一個關於setTimeout的筆試題
console.log(1) setTimeout(function() { console.log(2) },0) console.log(3) setTimeout(function() { console.log(4) },1000) console.log(5)
- 前端使用非同步的場景有哪些
知識點:
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執行多次,事件繫結的特點可以多次執行,執行機制與其他相同。
解答:
-
同步和非同步的區別是什麼?分別舉一個同步和非同步的例子
同步會阻塞,非同步不會阻塞,同步alert,非同步setTimeout -
一個關於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. - 前端使用非同步的場景有哪些
1.定時任務:setTimeout, setInterval
2.網路請求:ajax請求,動態<img>載入
3.事件繫結