javascript事件迴圈--強行梳理

来源:http://www.cnblogs.com/liuyushao/archive/2017/07/14/7171584.html
-Advertisement-
Play Games

js單線程 js是單線程的,這樣更有利與用戶交互以及DOM操作;有關進程與線程的詳細解釋可以點擊傳送門;儘管webworker可以實現多線程,但本質上他還屬於單線程,由webworker創建的線程都由主線程式控制制並且只能進行計算而已; js同步、非同步 同步執行:即js主線程按順序執行任務,如遇操作we ...


js單線程

js是單線程的,這樣更有利與用戶交互以及DOM操作;有關進程與線程的詳細解釋可以點擊傳送門;儘管webworker可以實現多線程,但本質上他還屬於單線程,由webworker創建的線程都由主線程式控制制並且只能進行計算而已;

 js同步、非同步

同步執行:即js主線程按順序執行任務,如遇操作webAPI/ajax等代碼時會等待其響應後面代碼得不到執行,也就是下一個任務必須等到前一個任務執行完成;

非同步執行:js是單線程的本身不具備非同步能力,但瀏覽器可以;當js執行時遇到webAPI(如setTimeout/ajax等),會立即返回一個值,從而不阻塞主線程,而真正的非同步由瀏覽器執行,待完成後講其回調函數推入js主線程的消息隊列中等待主線程調用;

事件迴圈機制[Event-loop]

js執行時其主線程擁有一個執行棧[個人習慣叫調用棧](stack)和一個消息列隊[也叫任務列隊或事件列隊](Event-queue);當js執行時遇到函數function時會將其入棧待函數執行完在出棧,主線程調用執行棧並執行,如果遇到webAPI會非同步執行;當執行棧中沒有任務時,主線程會查詢消息列隊,如查詢成功,則將查詢的任務入棧執行,直到執行棧為空,再次查詢消息列隊,這樣形成一個迴圈就是大名鼎鼎的事件迴圈[Event-loop];由於非同步執行是瀏覽器完成的這也就好理解為什麼js線程阻塞時操作dom事件會線上程恢復後依次執行,[js主線程的任務列隊是瀏覽器推入的,js線程阻塞!==瀏覽器線程阻塞,換言之即是主線程阻塞也不妨礙向任務列隊推入任務];畫個草圖;

再來段代碼:

      // 主線程執行fn1任務  1
            function fn1(){ 
                console.log("任務1執行")
                // 遇到webAPI立即返回 這裡是undefined值 並交給瀏覽器對應線程處理 2  
                // 瀏覽器收到後 0 毫秒將回調函數推入消息列隊; 非同步執行
                setTimeout(function(){// 查詢到一個回調任務 入棧執行    5
                console.log("回調1執行")
                    // 遇到webAPI立即返回 這裡是undefined值 並交給瀏覽器對應線程處理  6  
                    // 瀏覽器收到後 500   毫秒將回調函數推入消息列隊; 非同步執行
                    setTimeout(function(){// 查詢到一個回調任務 入棧執行    7
                        console.log("回調2執行")
                    },500)
                },0)
            }
            // 主線程執行fn2任務 3
            function fn2(){console.log("任務2執行")}
            // 執行棧沒有可執行任務 開始查詢消息列隊 4

Macrotasks 和 Microtasks

消息列隊分為兩種即Macrotasks[Task Queue]與Microtasks[Microtasks Queue ];

  • macrotaskssetTimeoutsetIntervalsetImmediate, I/O, UI rendering
  • microtasksprocess.nextTickPromisesObject.MutationObserver

這就引發一個問題他倆到底該誰先執行呢?Promise/A+規範指出:

Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called. 其實執行過程也是很好理解的也是一個迴圈查詢,在前面的基礎上查詢消息列隊時 會先查詢 microtasks將其所有任務執行完畢後在查詢macrotasks如果執行macrotasks中有microtasks任務則下次查詢依舊會先執行完microtasks列隊任務在查詢macrotasks 如此反覆 直到消息列隊[兩個 Queue]無任務; ok我們上段代碼[promise特性為es6 故用node環境]
console.log(1);
setTimeout(function(){
    console.log(7)
},0);
setTimeout(function(){
    new Promise(function(resolve){
        resolve();
    }).then(function(){
        console.log(8)
    }).then(function(){
        console.log(9)
    }).then(function(){
        console.log(10);
    })
},0);
new Promise(function(resolve){
    resolve();
}).then(function(){
    console.log(3)
}).then(function(){
    console.log(4)
}).then(function(){
    console.log(5)
}).then(function(){
    console.log(6)
})
console.log(2);
// 1 2 3 4 5 6 7 8 9 10

上邊代碼執行過程:

js執行console 1 遇到setTimeout改為非同步執行,又遇setTimeout再次非同步執行,接著執行遇到promise 被推入microtasks型任務列隊之後執行console 2 至此執行棧為空開始查詢消息列隊,先去查詢microtasks發現有個 有任務可以執行,接著會將任務入棧執行並相應列印 3 4 5 6【只要發現microtasks不為空就執行到為空為止】; 再次查詢消息列隊 此時microtasks列隊已無任務可執行,接著查詢macrotasks列隊發現一個setTimeout回調等待執行,接著入棧執行並出棧,列印 7 ;再次查詢列隊 此時microtasks列隊依然無任務,接著查詢macrotasks列隊又發現一個setTimeou回調等待執行,入棧執行 發現promise推入microtasks列隊 出棧,執行棧又空了。查詢消息列隊 此時發現microtasks有任務可以執行,入棧 執行 出棧;列印響應 8 9 10;至此執行結束主線程處於等待狀態;

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 做了一個網站,放到線上,用微信打開,點擊分享,可是分享後發給朋友的鏈接卡片是微信預設自帶的,如下: 這標題,描述以及圖片是預設自帶的,醜不說,分享給別人還以為是盜號網站呢,而接入微信的JSSDK後,分享可以自定義內容,如下: 我承認,雖然這分享的標題和內容也並不正經,但這不妨礙我表達 我們可以通過微 ...
  • 我們把這些用戶信息保存到list的數組中,然後增刪改查就在這個數組上進行: 這裡面的表單有:文本輸入框,單選按鈕,select選擇框,覆選框等。 1. 展示數據 我們的數據都放在數組list中,但是這裡並不直接對list對迴圈輸出,而是先把list中的數據給一個數組slist,對slist進行迴圈輸 ...
  • web前端開發的工作流程的第一步就是根據ui給的psd來還原設計圖樣貌。 可是一打開滿屏的參考線。這時我們可以alt+v+d清空參考線 這時可以按alt+滑鼠拖放圖片。同時也可以按F進入半屏和勻速連按兩次F進入全屏。F7為調出圖層面板。 下一步,是找到我們需要的圖層圖片。 (前提是設置了) 接著 總 ...
  • 一.概述 JavaScript一種直譯式腳本語言,是一種動態類型、弱類型、基於原型的語言,內置支持類型。它的解釋器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用於客戶端的腳本語言,最早是在HTML(標準通用標記語言下的一個應用)網頁上使用,用來給HTML網頁增加動態功能。 JavaScri ...
  • CSS3-loading載入動畫 線上示例demo:http://liyunpei.xyz/loading.html 之前發了四篇,二十二個效果,今天再分享六個效果,總計二十八個效果。 二十三、效果二十三 兩個正方形,初始均定位至左上(top:0;left:0;); 一次完整運動分為四個階段:第一個 ...
  • 在開發中,頁面 js 經常會遇到需要 當前登錄用戶信息(菜單許可權,用戶基本信息,配置信息) 的地方,一般情況我們可能對這些信息獲取方式不是太在意,但是現在的前端通過webpack打包,即使做了代碼分割,js文件,css文件還是很大。 在首次載入的情況下麵,存在一定的優化空間。下麵主要介紹一些信息獲... ...
  • <!DOCTYPE html><html><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <link rel="stylesheet" href=" ...
  • 本文github倉庫: "https://github.com/Rynxiao/webpack2 learn" 從v1遷移到v2 1. 配置類型 在webpack1的時候,主要是通過導出單個 來進行配置。例如下麵的配置: 而在webpack2中,則有三種方式來靈活配置,可以針對不同的場景。 1.1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...