国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

javascript中的event loop事件循環詳解

2024-05-06 16:47:06
字體:
來源:轉載
供稿:網友

前言

javascript是單線程的語言,也就是說,同一個時間只能做一件事。而這個單線程的特性,與它的用途有關,作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另一個線程刪除了這個節點,這時瀏覽器應該以哪個線程為準?

為了利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript腳本創建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標準并沒有改變JavaScript單線程的本質

這是今天一個朋友發給我的一個面試題,

感覺還挺有意思的,

寫個博客以供分享

先看看這個面試題目:

觀察下面的代碼,寫出輸出結果

console.log('0')setTimeout(function () { console.log('1');});new Promise(function(resolve,reject){ console.log('2') resolve(3)}).then(function(val){ console.log(val)})console.log(4)

輸出結果: “0” “2” 4 3 “1”

 

今天主要是分析為什么輸出結果是這樣的?這就和 javascript 的執行機制密切相關了.

Event Queue 和 Event Loop

javascript 是一門單線程的語言, 這就意味著在執行代碼的時候, 都只有一個主線程來處理所有的任務.

我們都知道 javascript 包括同步代碼和異步代碼, 那么 javascript 是怎么處理這兩種情況的呢?

  • 同步和異步任務分別進入不同的執行 場所, 同步的進入主線程,異步的進入 Event Table 并注冊函數
  • 當指定的事情完成時, Event Table 會將這個函數(回調函數)移入 Event Queue
  • 主線程內的任務執行完畢為空, 會去 Event Queue 讀取對應的函數,進入主線程執行
  • 上述過程會不斷重復, 也就是常說的 Event Loop(事件循環)

這里我們引進了 Event Queue 事件隊列這一概念. 所有異步操作的回調都會進入到這里. 然后等到主線程空閑, 就會從這里調取回調執行.

setTimeout

setTimeout 相信大家都有使用過, 可以延時執行并且是異步執行的.

但是有時候我們得到的結果往往是代碼實際執行的時間比我們想要延時執行的時間要久。這又是為什么呢?

這就和我們之前所說的 Event Loop 有關了, 我們可以來具體看下 setTimeout 的執行步驟:

setTimeout(function () {asyncFn()}, 1000);syncFn()
  • asyncFn 將異步執行函數放在 Event Table, 并且開始計時
  • 開始執行 syncFn, 但是 syncFn 可能需要處理的內容很多, 執行時間超過 1 秒, 但是計時還在繼續
  • 計時到達 1 秒, setTimeout 延時完成, asyncFn 進入 Event Queue 事件隊列, 但是主線程還在執行, 所以只能等待
  • syncFn 執行完成, 此時 asyncFn 從事件隊列中進入主線程執行

所以有時候會出現代碼實際執行時間比延時時間長的情況。

宏任務和微任務

之前我們說過異步任務會進入到事件隊列中, 不同類型的任務會進入到不同的隊列中, 比如宏任務會進入到宏任務隊列中, 微任務會進入到微任務隊列中.

我們只要記住 當當前執行棧執行完畢時會立刻先處理所有微任務隊列中的事件,然后再去宏任務隊列中取出一個事件。同一次事件循環中,微任務永遠在宏任務之前執行

這時候我們就可以解釋一開始的代碼執行結果了:

  • 主線程執行按順序代碼
  • 遇到 setTimeout, 回調進入到宏任務隊列上
  • 遇到 Promise, 立即執行, then 函數進入到微任務隊列
  • 同步代碼執行結束, 主線程檢查是否存在微任務, 發現 then, 執行
  • 微任務執行完畢, 再去查找宏任務 setTimeout, 執行
  • setTimeout 執行結束, 檢查是否存在微任務, 不存在, 結束.

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 石台县| 潮安县| 朔州市| 眉山市| 东乡族自治县| 梅州市| 大冶市| 芦山县| 嘉荫县| 浙江省| 广平县| 广宗县| 衡南县| 黄梅县| 清远市| 隆安县| 革吉县| 乌兰浩特市| 三都| 靖宇县| 濮阳县| 嘉鱼县| 大丰市| 雅安市| 卢龙县| 常德市| 黄陵县| 息烽县| 方山县| 文成县| 阳西县| 公安县| 璧山县| 神池县| 泰宁县| 宝兴县| 平潭县| 阳江市| 中超| 永和县| 沧州市|