JavaScript 為什么是單線程的?JavaScript 為什么需要異步?JavaScript 單線程又是如何實現異步的?
1.JavaScript 為什么是單線程的?
現在有 2 個線程 process1 process2,假設 JavaScript 是多線程的,所以他們可以對同一個 dom 同時進行操作。process1 刪除了該 dom,而 process2 編輯了該 dom,同時下達 2 個矛盾的命令,瀏覽器究竟該如何執行呢?這樣想,JavaScript 為什么被設計成單線程應該就容易理解了吧。
2.JavaScript 為什么需要異步?
如果 JavaScript 中不存在異步,只能自上而下執行,如果上一行解析時間很長,那么下面的代碼就會被阻塞。對於用戶而言,阻塞就意味着"卡死",這樣就導致了很差的用戶體驗,所以 JavaScript 中存在異步執行。
3.JavaScript 單線程又是如何實現異步的呢?
通過一個題看一下
setTimeout(function () { console.log(1) }, 0) Promise.resolve(function () { console.log(2) }) new Promise(function (resolve) { console.log(3) }) console.log(4) // 上述代碼的輸出結果是什么???
解釋
// 遇到 setTimeout 將 setTimeout 回調放入宏任務隊列中 setTimeout(function () { console.log(1) }, 0) // 遇到了 promise,但是並沒有 then 方法回調 // 所以這句代碼會在執行過程中進入我們當前的執行上下文 緊接着就出棧了 Promise.resolve(function () { console.log(2) }) // 遇到了一個 new Promise,Promise 有一個原則就是在初始化 Promise 的時候Promise 內部的構造器函數會立即執行, // 因此在這里會立即輸出一個 3,所以這個 3 是第一個輸出的 new Promise(function (resolve) { console.log(3) }) // 然后第二個輸出 4 當代碼執行完畢后回去微任務隊列查找有沒有任務, // 發現微任務隊列是空的,那么就去宏仁務隊列中查找,發現有一個我們剛剛放進去的setTimeout 回調函數, // 那么就取出這個任務進行執行,所以緊接着輸出1 console.log(4)
答案 ==》 3 4 2 1
任務隊列
當遇到一個異步事件后,JavaScript 引擎並不會一直等待異步事件返回結果,而是會將這個事件掛在與執行棧不同的隊列中,我們稱之為任務隊列。
這些任務又被細分為宏任務和微任務
在主線程的任務 全部執行完畢,就會清空微任務,然后去宏任務隊列中取出一條宏任務,放在主任務中執行,主任務執行完畢,清空微任務,再去宏任務中取任務,一直循環執行,
宏任務(macrotask):script(全局任務),setTimeout ,setInterval ,setImmediate (node.js 獨有),I/O(磁盤讀寫或網絡通信) ,UI rendering(UI交互事件)
微任務(microtask):process.nextTick (node.js 獨有), Promise.then