JavaScript 語言的一大特色就是單線程,也就是說,同一個時間只能作一件事。javascript
單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。這樣所致使的問題是: 若是 JS 執行的時間過長,這樣就會形成頁面的渲染不連貫,致使頁面渲染加載阻塞的感受。java
// 如下代碼會輸出什麼
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);
// 1
// 2
// 3
複製代碼
爲了解決這個問題,利用多核 CPU 的計算能力,HTML5 提出 Web Worker 標準,容許 JavaScript 腳本建立多個線程。因而,JS 中出現了同步和異步。dom
前一個任務結束後再執行後一個任務,程序的執行順序與任務的排列順序是一致的、同步的。好比作飯的同步作法:咱們要燒水煮飯,等水開了(10分鐘以後),再去切菜,炒菜。異步
同步任務都在主線程上執行,造成一個執行棧。函數
你在作一件事情時,由於這件事情會花費很長時間,在作這件事的同時,你還能夠去處理其餘事情。好比作飯的異步作法,咱們在燒水的同時,利用這10分鐘,去切菜,炒菜。ui
JS 的異步是經過回調函數實現的。spa
異步任務有如下三種類型:線程
1,普通事件,如 click、resize 等code
2,資源加載,如 load、error 等cdn
3,定時器,包括 setInterval、setTimeout 等
異步任務相關回調函數添加到任務隊列中(任務隊列也稱爲消息隊列)
1,先執行執行棧中的同步任務。
2,異步任務(回調函數)放入任務隊列中。
3,一旦執行棧中的全部同步任務執行完畢,系統就會按次序讀取任務隊列中的異步任務,因而被讀取的異步任務結束等待狀態,進入執行棧,開始執行。
console.log(1);
document.onclick = function() {
console.log('click');
}
console.log(2);
setTimeout(function() {
console.log(3)
}, 3000)
// 1
// 2
// 3 (3秒鐘後打印3)
複製代碼
var dom02 = function(i) {
setTimeout(function() {
console.log(i);
}, 1000);
}
for (var i = 0; i < 3; i++) {
dom02(i);
};
console.log(i);
// 3 (先打印3)
// 0
// 1
// 2
複製代碼