什麼是js異步?
我們常常聽到單線程、多線程、同步、異步這些概念,那麼這些東西到底是什麼呢?
1.單線程就是隻有一個主線的線程,代碼從上往下順序運行,主線程負責執行程序的所有代碼(UI展現以及刷新,網絡請求,本地存儲等等)
例如:一個項目從產品邏輯 => 設計原型圖 => 前端+後臺 => 測試 => 發佈上線 ,這些流程都是由你自己來完成就是單線程
2.多線程顧名思義,就是有多個線程的程序,可以由用戶自主創建。用戶自主創建的若干進程相對於主線程而言就是子線程。子線程和主線程都是獨立的運行單元,各自的執行互不影響,因此能夠併發執行。
例如:一個項目分了多種流程 然後每個人只負責其中一部分,各自都有各自負責的一部分,一起合作完成這個項目就是多線程
3.同步的意思就像你在電話上要預約一個酒店,問前臺有沒有房間,然後沒有掛掉電話,一直等,直到前臺查詢完有沒有房間再回答你
4.異步就是你在電話上要預約一個酒店,問前臺有沒有房間,然後先掛掉電話,你可以做一些其他事情,然後等前臺查詢之後再給你回個電話告訴你
廢話不多說直接上代碼感受下:
異步-定時器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript異步</title>
</head>
<body>
<script>
console.log("我是1")
setTimeout(() =》{
console.log("我是定時器")
},500)
console.log("我是2")
</script>
</body>
</html>
看下輸出,沒什麼意外:
異步-ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript異步</title>
</head>
<body>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script>
let allData = null;
function ajax() {
axios.get('https://easy-mock.com/mock/5c249dbe46e8386d0b21b475/example_copy_copy/test')
.then(data => {
console.log("ajax返回成功");
allData = data.data
console.log(allData );
}).catch(error => {
console.log("ajax返回失敗");
})
}
ajax()
</script>
</body>
</html>
看下輸出,仍在我們意料之中:
但是如果兩個異步函數相遇了呢?上代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript異步</title>
</head>
<body>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script>
let allData = null;
function ajax() {
axios.get('https://easy-mock.com/mock/5c249dbe46e8386d0b21b475/example_copy_copy/test')
.then(data => {
console.log("ajax返回成功");
allData = data.data.data
console.log(allData );
}).catch(error => {
console.log("ajax返回失敗");
})
}
console.log("我是1")
setTimeout(() =>{
console.log("我是定時器")
},500)
ajax()
console.log("我是2")
</script>
</body>
</html>
輸出:
發現問題了嗎?兩個異步函數相遇了,先執行誰?誰跑的快就先執行誰?
也可以這麼說,那麼現在又引出一個知識點
任務隊列和事件循環
console.log(“我是1”)與console.log(“我是2”);是同步執行的,他們都在js的主線程上執行,
在主線程之外還存在一個任務隊列,任務隊列中存放着需要異步執行的內容
當主線程運行完畢之後,就會去執行任務隊列中的任務(不斷的重複掃描)直到任務隊列清空
繼續看代碼
setTimeout(function(){
console.log("我是定時器")
}, 0);
console.log("我是1");
輸出:
爲什麼會這樣?
console.log(“我是1”);在主線程中,先執行,
定時器是異步操作所以把定時器的內容,放在了任務隊列中,
只有在主線程執行完了纔會去執行任務列隊中的內容
爲什麼主線程的任務執行完了後需要不斷的掃描任務列隊中的內容呢?
繼續上代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript異步</title>
</head>
<body>
<button class="btn">點擊</button>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script>
let btn = document.querySelector('.btn');
let allData = null;
function ajax() {
axios.get('https://easy-mock.com/mock/5c249dbe46e8386d0b21b475/example_copy_copy/test')
.then(data => {
console.log("ajax返回成功");
allData = data.data.data
console.log(allData );
}).catch(error => {
console.log("ajax返回失敗");
})
}
console.log("我是1")
setTimeout(() =>{
console.log("我是定時器")
},500)
ajax()
console.log("我是2")
btn.onclick = () =>{
console.log("我點擊了")
}
</script>
</body>
</html>
爲button按鈕綁定點擊事件,在頁面刷新的時候一直點擊它 輸出:
這樣是不是可以理解爲什麼主線程要去循環掃描任務列隊了?
事件循環的每一輪稱爲一個tick,類似vue中nextTick;擴展閱讀:vue.nextTick
當產生用戶交互(頁面滾動事件,鼠標點擊事件,窗口大小變化事件等等),ajax,定時器,計時器等,會向事件循環中的任務隊列添加事件,然後等待執行
預知後事如何,且聽下次分解