天天看點

setTimeout和異步隊列

```

for(var i=0;i<= 100;i++){

if(i===1){

setTimeout(function(){console.log("timeout")},0)

}

console.log(i)

}

```

當真正運作的時候你會發現,這個"timeout"文字會在整個for執行完之後再執行,而不是想當然的在某一步運作完之後執行。

setTimeout/setInterval

DOM事件,有時候點選事件會卡死,就是因為目前js正在處理,無法将click觸發事件放入執行棧

Promise也是異步隊列

JS的異步機制由事件循環和任務隊列構成.JS本身是單線程語言,所謂異步依賴于浏覽器或者作業系統等完成. JavaScript 主線程擁有一個執行棧以及一個任務隊列,主線程會依次執行代碼,當遇到函數時,會先将函數入棧,函數運作完畢後再将該函數出棧,直到所有代碼執行完畢。

遇到異步操作(例如:setTimeout, AJAX)時,異步操作會由浏覽器(OS)執行,浏覽器會在這些任務完成後,将事先定義的回調函數推入主線程的任務隊列(task queue)中,當主線程的執行棧清空之後會讀取task queue中的回調函數,當task queue被讀取完畢之後,主線程接着執行,進而進入一個無限的循環,這就是事件循環.

JavaScript是單線程執行的,無法同時執行多段代碼。當某一段代碼正在執行的時候,所有後續的任務都必須等待,形成一個隊列。一旦目前任務執行完畢,再從隊列中取出下一個任務,這也常被稱為 “阻塞式執行”。是以一次滑鼠點選,或是計時器到達時間點,或是Ajax請求完成觸發了回調函數,這些事件處理程式或回調函數都不會立即運作,而是立即排隊,一旦線程有空閑就執行。假如目前 JavaScript線程正在執行一段很耗時的代碼,此時發生了一次滑鼠點選,那麼事件處理程式就被阻塞,使用者也無法立即看到回報,事件處理程式會被放入任務隊列,直到前面的代碼結束以後才會開始執行。如果代碼中設定了一個 setTimeout,那麼浏覽器便會在合适的時間,将代碼插入任務隊列,如果這個時間設為 0,就代表立即插入隊列,但不是立即執行,仍然要等待前面代碼執行完畢。是以 setTimeout 并不能保證執行的時間,是否及時執行取決于 JavaScript 線程是擁擠還是空閑。