摘要:即使現在支持,由于沒有多線程的機制,和執行線程只能通過來通信,而且由于沒有鎖,無法訪問和對象。的單線程是指一個瀏覽器進程中只有一個的執行線程,即同一時刻內只會有一段代碼在執行。與單線程如何實現異步設計了一個事件循環的方式。
眾所周知,JavaScript(以下簡稱 JS) 是單線程語言,在 html5 中增加了 web workers,web workers 是新開了線程執行的,那么 JS 還是單線程的嗎?當然是,為什么要設計成單線程?
網上有很多說法,大部分都說是多個線程同時對一個dom操作(同時修改dom內容,一個線程增加屬性,一個線程刪除屬性),會非常混亂,當然如果支持多線程就會相應的就要加入多線程的鎖機制,那么 JS 就變得非常復雜了,想想 JS 最開始設計的初衷就是用于用戶交互,而且當時的原始需求是:功能不需要太強,語法較為簡單,容易學習和部署,Brendan Eich 只用了10天,就設計完成了這種語言的第一版,因此也不可能加入多線程這么復雜的技術。
即使現在支持 web workers,由于沒有多線程的機制,web workers 和執行線程只能通過 postMessage 來通信,而且由于沒有鎖,web workers 無法訪問 window 和 document 對象。
Micro-Task 與 Macro-TaskJS 的單線程是指一個瀏覽器進程中只有一個 JS 的執行線程,即同一時刻內只會有一段代碼在執行。
單線程如何實現異步?JS 設計了一個事件循環的方式。所有的代碼執行均按照事件循環的方式進行。
事件循環中分兩種任務:一個是宏任務(Macro-Task),另一個是微任務(Micro-Task)。常見的宏任務和微任務如下。
宏任務:script(整體代碼)、setTimeout、setInterval、requestAnimationFrame、I/O、事件、MessageChannel、setImmediate (Node.js) 微任務:Promise.then、 MutaionObserver、process.nextTick (Node.js)
事件循環按下圖的方式進行。
注意: 宏任務執行完后,需要清空當前微任務隊列后才回去執行下一個宏任務,如果微任務里面產生了新的微任務,仍然會在當前事件循環里面被執行完,后面會舉例說明。
來個示例驗證下上面的流程。
<script>
console.log(1);
setTimeout(function timeout1() {
console.log(2);
}, 0);
Promise.resolve().then(function promise1() {
console.log(3);
setTimeout(function timeout2() {
console.log(4);
Promise.resolve().then(function promise2() {
console.log(5);
});
}, 0);
return Promise.resolve()
.then(function promise3() {
console.log(6);
return Promise.resolve().then(function promise4() {
console.log(7);
});
})
.then(function promise5() {
console.log(8);
});
})
console.log(9);
script>
<script>
console.log(10);
setTimeout(function timeout3() {
console.log(11);
}, 0);
Promise.resolve().then(function promise6() {
console.log(12);
});
script>
按照上面流程梳理下執行流程:
將兩個宏任務(兩個script代碼)初始化進宏任務隊列,宏任務隊列為:[script1, script2]
script1 出隊壓入執行棧執行,宏任務隊列為:[script2]
同步代碼執行輸出:1,
timeout1 入隊,宏任務隊列為:[script2, timeout1]
promise1 入隊,微任務隊列為:[promise1]
同步代碼執行輸出:9
script1 執行完畢,進入微任務執行階段,promise1 出隊壓入執行棧執行,微任務隊列為空
同步代碼執行輸出:3
timeout2 入隊,宏任務隊列為:[script2, timeout1, timeout2]
promise3 入隊,微任務隊列為:[promise3]
promise1 執行完畢,繼續判斷微任務隊列是否為空,promise3 出隊壓入執行棧執行,微任務隊列為空
同步代碼執行輸出:6
promise4 入隊,微任務隊列為:[promise4]
promise3 執行完畢,promise5 入隊,微任務隊列為:[promise4,promise5]
判斷微任務隊列是否為空,promise4 出隊壓入執行棧執行,微任務隊列為:[promise5]
同步代碼執行輸出:7
promise4 執行完畢,繼續判斷微任務隊列是否為空,promise5 出隊壓入執行棧執行,微任務隊列為空
同步代碼執行輸出:8
微任務隊列清空,宏任務 script2 出隊壓入執行棧執行,宏任務隊列為[ timeout1, timeout2]
同步代碼執行輸出:10
timeout3 入隊,宏任務隊列為:[timeout1, timeout2, timeout3]
promise6 入隊,微任務隊列為:[promise6]
script2 執行完畢,進入微任務執行階段,promise6 出隊壓入執行棧執行,微任務隊列為空
同步代碼執行輸出:12
微任務隊列為空,執行宏任務隊列,timeout1 判斷是否到時間,timeout1 到時壓入執行棧執行,宏任務隊列為[ timeout2, timeout3]
同步代碼執行輸出:2
微任務隊列為空,執行宏任務隊列,timeout2 判斷是否到時間,timeout2 到時壓入執行棧執行,宏任務隊列為[ timeout3]
同步代碼執行輸出:4,promise2 入隊,微任務隊列為:[promise2]
timeout2 執行完畢,判斷微任務隊列是否為空,promise2 出隊壓入執行棧執行,微任務隊列為空
同步代碼執行輸出:5
微任務隊列為空,執行宏任務隊列,timeout3 判斷是否到時間,timeout3 到時壓入執行棧執行,宏任務隊列為空
同步代碼執行輸出:11
宏任務隊列為空
JavaScript語言的歷史
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/6834.html
摘要:深入理解引擎的執行機制最近在反省,很多知識都是只會用,不理解底層的知識。在閱讀之前,請先記住兩點是單線程語言的是的執行機制。所以,是存在異步執行的,比如單線程是怎么實現異步的場景描述通過事件循環,所以說,理解了機制,也就理解了的執行機制啦。 深入理解js引擎的執行機制 最近在反省,很多知識都是只會用,不理解底層的知識。所以在開發過程中遇到一些奇怪的比較難解決的bug,在思考的時候就會收...
摘要:深入理解引擎的執行機制靈魂三問為什么是單線程的為什么需要異步單線程又是如何實現異步的呢中的中的說說首先請牢記點是單線程語言的是的執行機制。 深入理解JS引擎的執行機制 1.靈魂三問 : JS為什么是單線程的? 為什么需要異步? 單線程又是如何實現異步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.說說setTimeout 首先,請牢記2...
摘要:曾經的理解首先,是單線程語言,也就意味著同一個時間只能做一件事,那么為什么不是多線程呢這樣還能提高效率啊假定同時有兩個線程,一個線程在某個節點上編輯了內容,而另一個線程刪除了這個節點,這時瀏覽器就很懵逼了,到底以執行哪個操作呢所以,設計者把 Event Loop曾經的理解 首先,JS是單線程語言,也就意味著同一個時間只能做一件事,那么 為什么JavaScript不是多線程呢?這樣還能提...
摘要:的單線程,與它的用途有關。只要指定過回調函數,這些事件發生時就會進入任務隊列,等待主線程讀取。四主線程從任務隊列中讀取事件,這個過程是循環不斷的,所以整個的這種運行機制又稱為事件循環。令人困惑的是,文檔中稱,指定的回調函數,總是排在前面。 原文:http://www.cnblogs.com/Master... 一、為什么JavaScript是單線程? JavaScript語言的一大特點...
摘要:圖片轉引自的演講和兩個定時器中回調的執行邏輯便是典型的機制。異步編程關于異步編程我的理解是,在執行環境所提供的異步機制之上,在應用編碼層面上實現整體流程控制的異步風格。 問題背景 在一次開發任務中,需要實現如下一個餅狀圖動畫,基于canvas進行繪圖,但由于對于JS運行環境中異步機制的不了解,所以遇到了一個棘手的問題,始終無法解決,之后在與同事交流之后才恍然大悟。問題的根節在于經典的J...
摘要:中叫做調用棧先進后出,后進先出。如下圖這是典型的內存溢出,可能會出現在某些場景下需要遞歸,但業務邏輯中的判斷又沒能正常計算進入到預設情況,于是調用棧中不斷進入,又無法執行完,就造成內存溢出了。 本文主要介紹Javascript事件循環在瀏覽器上的一些特性和應用介紹。 Javascript小知識 JavaScript的并發模型基于事件循環(Event Loop)。這個模型與像C或者Jav...
閱讀 2804·2021-11-24 09:39
閱讀 2777·2021-09-23 11:45
閱讀 3403·2019-08-30 12:49
閱讀 3352·2019-08-30 11:18
閱讀 1908·2019-08-29 16:42
閱讀 3344·2019-08-29 16:35
閱讀 1321·2019-08-29 11:21
閱讀 1912·2019-08-26 13:49