JS中的非同步
Hello,日常更新的我“浪”回來了!!!
JS中有三座高山:非同步和單執行緒、作用域和閉包、原型原型鏈
今天“浪”的主題是JS中的非同步和單執行緒的問題。
主要從這三個方面入手
一、什麼是非同步(與同步作比較)
二、前端使用非同步的場景
三、非同步和單執行緒
一:什麼是非同步
說非同步之前我們先了解一下同步:同步可以簡單的來說就是順序執行
console.log(100); alert(200) //點選確定往下執行,如果不點選確定,就會阻塞不往下執行 console.log(300) //列印100,彈出200(點選確定往下執行),列印300
接下來我們來說非同步(當執行非同步程式碼時,不會影響另一些程式碼執行)
console.log(100); setTimeout(function() { //非同步執行,非阻塞並不妨礙後續程式碼執行 console.log(300) }, 1000); console.log(200)
這段程式碼的執行結果為:
非同步和同步的區別就在於:
同步:會阻塞後續程式碼的執行
非同步:不會阻塞程式碼執行
二:前端使用非同步的場景
1、定時任務:setTimeout 、 setInterval(程式碼同上)
2、網路請求 :ajax請求、動態的建立<img>載入、
console.log("start") $.get("./data.json",(data)=>{ console.log(data) }) console.log("end") //列印start,列印end 等待獲取回撥函式傳來的data資料渲染頁面 //為啥ajax要用非同步呢?因為向伺服器請求資料,誰也不知道多長時間能返回資料(有可能幾秒,有可能拿不到資料) 如果資料拿不到,頁面肯定還是要正常顯示的,所以必須是非同步
console.log("start") var img = document.createElement("img"); img.onload =function(){ console.log("img is onload") } img.src='/aa.png' console.log("end") //列印start,列印end,載入圖片
3、事件繫結
console.log("start") document.getElementById("btn").addEventListener("click",()=>{ //ES6箭頭函式 console.log("click is finshed") }) console.log("end") //列印start,列印end,載入圖片
三 、非同步和單執行緒
下面程式碼和介紹非同步的程式碼區別是延時器沒有設定時間
console.log(100); setTimeout(function() { console.log(300) }); console.log(200)
執行順序:
先列印100,
執行setTimeout,這個函式會被暫存起來,不會立即執行(因為單執行緒只能一個一個執行)
列印300,
等待所有的程式執行完後,瀏覽器會看有沒有暫存的,
暫存裡面有setTimeout,setTimeout沒有設定時間,不用等待然後立刻執行
那什麼叫單執行緒呢??
簡單來說就是一次只能幹一件事,一個一個排隊,不能多個一起執行(因為不是多執行緒)
標準定義:瀏覽器只分配給js一個主執行緒,用來執行任務(函式),但一次只能執行一個任務,這些任務形成一個任務佇列排隊等候執行,
但前端的某些任務是非常耗時的,比如網路請求,定時器和事件監聽,如果讓他們和別的任務一樣,都老老實實的排隊等待執行的話,
執行效率會非常的低,甚至導致頁面的假死。所以,瀏覽器為這些耗時任務開闢了另外的執行緒,主要包括http請求執行緒,瀏覽器定時觸發器,
瀏覽器事件觸發執行緒,這些任務是非同步的。