91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中的事件循環機制是什么

發布時間:2021-06-16 16:03:09 來源:億速云 閱讀:159 作者:Leah 欄目:web開發

這期內容當中小編將會給大家帶來有關JavaScript中的事件循環機制是什么,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

眾所周知,JavaScript 是一門單線程語言,雖然在 html5 中提出了 Web-Worker ,但這并未改變 JavaScript 是單線程這一核心。可看HTML規范中的這段話:

To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. There are two kinds of event loops: those for browsing contexts, and those for workers.

為了協調事件、用戶交互、腳本、UI 渲染和網絡處理等行為,用戶引擎必須使用 event loops。Event Loop 包含兩類:一類是基于 Browsing Context ,一種是基于 Worker ,二者是獨立運行的。 下面本文用一個例子,著重講解下基于 Browsing Context 的事件循環機制。

來看下面這段 JavaScript 代碼:

console.log('script start');

setTimeout(function() {
 console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
 console.log('promise1');
}).then(function() {
 console.log('promise2');
});

console.log('script end');

先猜測一下這段代碼的輸出順序是什么,再去瀏覽器控制臺輸入一下,看看實際輸出的順序和你猜測出的順序是否一致,如果一致,那就說明,你對 JavaScript 的事件循環機制還是有一定了解的,繼續往下看可以鞏固下你的知識;而如果實際輸出的順序和你的猜測不一致,那么本文下面的部分會為你答疑解惑。

任務隊列

所有的任務可以分為同步任務和異步任務,同步任務,顧名思義,就是立即執行的任務,同步任務一般會直接進入到主線程中執行;而異步任務,就是異步執行的任務,比如ajax網絡請求,setTimeout 定時函數等都屬于異步任務,異步任務會通過任務隊列( Event Queue )的機制來進行協調。具體的可以用下面的圖來大致說明一下:

JavaScript中的事件循環機制是什么

同步和異步任務分別進入不同的執行環境,同步的進入主線程,即主執行棧,異步的進入 Event Queue 。主線程內的任務執行完畢為空,會去 Event Queue 讀取對應的任務,推入主線程執行。 上述過程的不斷重復就是我們說的 Event Loop (事件循環)。

在事件循環中,每進行一次循環操作稱為tick,通過閱讀規范可知,每一次 tick 的任務處理模型是比較復雜的,其關鍵的步驟可以總結如下:

  • 在此次 tick 中選擇最先進入隊列的任務( oldest task ),如果有則執行(一次)

  • 檢查是否存在 Microtasks ,如果存在則不停地執行,直至清空Microtask Queue

  • 更新 render

主線程重復執行上述步驟

可以用一張圖來說明下流程:

JavaScript中的事件循環機制是什么

這里相信有人會想問,什么是 microtasks ?規范中規定,task分為兩大類, 分別是 Macro Task (宏任務)和 Micro Task(微任務), 并且每個宏任務結束后, 都要清空所有的微任務,這里的 Macro Task也是我們常說的 task ,有些文章并沒有對其做區分,后面文章中所提及的task皆看做宏任務( macro task)。

(macro)task 主要包含:script( 整體代碼)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 環境)

microtask主要包含:Promise、MutaionObserver、process.nextTick(Node.js 環境)

setTimeout/Promise 等API便是任務源,而進入任務隊列的是由他們指定的具體執行任務。來自不同任務源的任務會進入到不同的任務隊列。其中 setTimeout 與 setInterval 是同源的。

分析示例代碼

千言萬語,不如就著例子講來的清楚。下面我們可以按照規范,一步步執行解析下上面的例子,先貼一下例子代碼(免得你往上翻)。

console.log('script start');

setTimeout(function() {
 console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
 console.log('promise1');
}).then(function() {
 console.log('promise2');
});

console.log('script end');

整體 script 作為第一個宏任務進入主線程,遇到 console.log,輸出 script start

  • 遇到 setTimeout,其回調函數被分發到宏任務 Event Queue 中

  • 遇到 Promise,其 then函數被分到到微任務 Event Queue 中,記為 then1,之后又遇到了 then 函數,將其分到微任務 Event Queue 中,記為 then2

  • 遇到 console.log,輸出 script end

至此,Event Queue 中存在三個任務,如下表:

宏任務微任務
setTimeoutthen1
-then2
  • 執行微任務,首先執行then1,輸出 promise1, 然后執行 then2,輸出 promise2,這樣就清空了所有微任務

  • 執行 setTimeout 任務,輸出 setTimeout 至此,輸出的順序是:script start, script end, promise1, promise2, setTimeout

so,你猜對了嗎?

看看你掌握了沒

再來一個題目,來做個練習:

console.log('script start');

setTimeout(function() {
 console.log('timeout1');
}, 10);

new Promise(resolve => {
 console.log('promise1');
 resolve();
 setTimeout(() => console.log('timeout2'), 10);
}).then(function() {
 console.log('then1')
})

console.log('script end');

這個題目就稍微有點復雜了,我們再分析下:

首先,事件循環從宏任務 (macrotask) 隊列開始,最初始,宏任務隊列中,只有一個 scrip t(整體代碼)任務;當遇到任務源 (task source) 時,則會先分發任務到對應的任務隊列中去。所以,就和上面例子類似,首先遇到了console.log,輸出 script start; 接著往下走,遇到 setTimeout 任務源,將其分發到任務隊列中去,記為 timeout1; 接著遇到 promise,new promise 中的代碼立即執行,輸出 promise1, 然后執行 resolve ,遇到 setTimeout ,將其分發到任務隊列中去,記為 timemout2, 將其 then 分發到微任務隊列中去,記為 then1; 接著遇到 console.log 代碼,直接輸出 script end 接著檢查微任務隊列,發現有個 then1 微任務,執行,輸出then1 再檢查微任務隊列,發現已經清空,則開始檢查宏任務隊列,執行 timeout1,輸出 timeout1; 接著執行 timeout2,輸出 timeout2 至此,所有的都隊列都已清空,執行完畢。其輸出的順序依次是:script start, promise1, script end, then1, timeout1, timeout2

用流程圖看更清晰:

JavaScript中的事件循環機制是什么

上述就是小編為大家分享的JavaScript中的事件循環機制是什么了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

农安县| 闽侯县| 汝阳县| 广宗县| 九江市| 迁西县| 荔浦县| 文登市| 岐山县| 屏南县| 潞西市| 东港市| 乐平市| 芦山县| 博乐市| 肥城市| 于田县| 庆安县| 沂水县| 漾濞| 漠河县| 荆门市| 新乡县| 隆安县| 湛江市| 三亚市| 阿勒泰市| 房产| 曲靖市| 娄底市| 河津市| 英吉沙县| 资中县| 黄浦区| 赤城县| 平利县| 南澳县| 达尔| 永定县| 南木林县| 当涂县|