setTimeout真的是異步的嗎????

這是假象!!!!

1??、單線程

JavaScript語言的執(zhí)行環(huán)境是單線程

所謂單線程就是同一時間只能做一件事情 如果有多件事件就必須排隊 后面的事情必須等前面的事情完成后才能執(zhí)行

這種單線程的模式的好處就是實現起來比較簡單 執(zhí)行環(huán)境相對單純
壞處是 只要有一個任務耗時很長 后面的任務都必須排隊等待 會拖延整個程序的執(zhí)行 如:
瀏覽器無響應(假死) 往往就是因為某一段代碼長時間運行 (如死循環(huán)) 導致整個頁面都卡在了這個地方 其他代碼無法執(zhí)行

那么為什么JavaScript不能有多個線程呢?

JavaScript作為瀏覽器的腳本語言 最主要的用途就是與用戶進行交互 這決定了它只能是單線程 否則就會帶來很復雜的同步問題
如: 假設JavaScript同時有兩個線程 一個線程在刪除一個元素 另一個線程又在這個元素上添加內容 那么這個時候瀏覽器該如何處理呢?
因為不能確定在同時執(zhí)行這兩段代碼時 刪除元素一定在添加內容之后 如在之前就會報錯
所以 為了避免復雜性 從一誕生 JavaScript就是單線程的


2??、驗證

簡單兩點聊異步: 不阻塞主線程 同時執(zhí)行
通過一段代碼來解釋 setTimeout 不是異步的

console.log(111)
setTimeout(() => {
    console.log(222);
}, 3000)
console.log(333)
setTimeout(() => {
    console.log(444);
}, 0)
console.log(555)
setTimeout(() => {
    console.log(666);
}, 1000)

最后控制臺輸出的結果是??

111
333
555
444 // 等待0秒
666 // 等待1秒
222 // 等待3秒

從這段代碼執(zhí)行的順序以及執(zhí)行的時間可以看出
雖然setTimeout沒有阻塞主線程 但也沒有同時執(zhí)行 在執(zhí)行完1 3 5后才執(zhí)行等待時間后的4 6 2 所以不能說setTimeout是異步的 它雖滿足了沒有阻塞主線程 但是它也等待了 等待主線程全部執(zhí)行完成后再執(zhí)行

那么為什么setTimeout執(zhí)行的時候并沒有阻塞主線程呢???? 這都歸功于瀏覽器的任務隊列


3??、任務隊列

在JavaScript中 所有的任務可以分為兩種 一種是同步任務(synchronous)另一種是異步任務(asynchronous)
同步任務指: 在主線程上排隊執(zhí)行的任務 只有前一個任務執(zhí)行完畢后 才能執(zhí)行下一個任務
異步任務指: 不進入主線程 而進入 任務隊列(task queue)的任務 等主線程的任務全部執(zhí)行完成后 主線程會通過event loop(事件循環(huán)) 去詢問任務隊列中是否有可以被執(zhí)行的任務了 如果有可以被執(zhí)行的任務 這個時候這個任務就會被放進 主線程執(zhí)行

下面這張圖就更詳細的解釋了主線程和任務隊列的關系

至此 setTimeout并不是異步的 而是JavaScript在執(zhí)行的時候 會將setTimeout放入任務隊列 等待主線程的執(zhí)行(不阻塞主線程)全部執(zhí)行完成后 再通過event loop去詢問任務隊列中是否有可執(zhí)行的代碼 再繼續(xù)放入主線程中執(zhí)行 故產生了異步的假象。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容