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請求線程,瀏覽器定時觸發器,
瀏覽器事件觸發線程,這些任務是異步的。