## 從瀏覽器接收url到開啟網絡請求線程
### 進程和線程
首先明確一下進程和線程的概念 :
- 進程是cpu資源分配的最小單位(是能擁有資源和獨立運行的最小單位)
- 線程是cpu調度的最小單位(線程是建立在進程的基礎上的一次程序運行單位,一個進程中可以有多個線程)
### 多進程的瀏覽器
首先需要知道,瀏覽器是一個多進程的應用程序,它有一個主控進程,以及每一個tab頁面都會新開一個進程(某些情況下多個tab會合并進程),除此之外,可能還包括插件進程,GPU,瀏覽器內核等等。
看下面一個圖:
:-: 
:-: 
我打開了 Chrome 瀏覽器,在任務管理器中可以看到,實際上瀏覽器創建了多個進程。
#### 瀏覽器都包含哪些進程?
知道了瀏覽器是多進程后,再來看看它到底包含哪些進程:(為了簡化理解,僅列舉主要進程)
1. **Browser進程**:瀏覽器的主進程(負責協調、主控),只有一個。作用有
- 負責瀏覽器界面顯示,與用戶交互。如前進,后退等
- 負責各個頁面的管理,創建和銷毀其他進程
- 將Renderer進程得到的內存中的Bitmap,繪制到用戶界面上
- 網絡資源的管理,下載等
2. **第三方插件進程**:每種類型的插件對應一個進程,僅當使用該插件時才創建
3. **GPU進程**:最多一個,用于3D繪制等
4. **瀏覽器渲染進程**(瀏覽器內核)(Renderer進程,內部是多線程的):默認每個Tab頁面一個進程(有時候會優化,如多個空白tab會合并成一個進程),互不影響。主要作用為 控制頁面渲染,腳本執行,事件處理 等
可以通過 Chrome 的 更多工具 -> 任務管理器 驗證 :
:-: 
#### 瀏覽器多進程的優勢
相比于單進程瀏覽器,多進程有如下優點:
- 避免單個page crash影響整個瀏覽器
- 避免第三方插件crash影響整個瀏覽器
- 多進程充分利用多核優勢
- 方便使用沙盒模型隔離插件等進程,提高瀏覽器穩定性
簡單點理解:**如果瀏覽器是單進程,那么某個Tab頁崩潰了,就影響了整個瀏覽器,體驗有多差;同理如果是單進程,插件崩潰了也會影響整個瀏覽器。**
當然,內存等資源消耗也會更大,有點空間換時間的意思。
#### 而至于多核多線程 CPU ?
在配置電腦的時候,我們經常會談到 CPU 有多少核心,每個核心多少個線程,而瀏覽器同時開啟如此多的進程,每個進程又開啟那么多的線程,從數量上看,CPU 似乎不能負荷那么多,但實際上,CPU 是使用時間片進行分時處理,由于切分的時間間隔特別的短,作為我們普通人根本感覺不到,因此感覺到所有程序都是并行處理的,實際上,比如 4核心雙線程的 CUP 同時最多只能進行 8 個工作的處理,但由于時間片切分的時間特別短,以至于我們感覺所有程序都是并行處理的。
### 多線程的瀏覽器內核
每一個tab頁面可以看作是瀏覽器內核進程,然后這個進程是多線程的,它有幾大類子線程
- GUI 線程
- JS 引擎線程
- 事件觸發線程
- 定時器線程
- 網絡請求線程
:-: 
可以看到,里面的JS引擎是內核進程中的一個線程,這也是為什么常說JS引擎是單線程的。
可以這樣簡單的理解: 瀏覽器每一個進程就是一個大工廠,而進程中的每一個線程就是工廠里面干活的各種工人。
#### 重點是瀏覽器內核(渲染進程)
重點來了,我們可以看到,上面提到了這么多的進程,那么,對于普通的前端操作來說,最終要的是什么呢?答案是**渲染進程**
可以這樣理解,頁面的渲染,JS的執行,事件的循環,都在這個進程內進行。接下來重點分析這個進程
**請牢記,瀏覽器的渲染進程是多線程的**
終于到了線程這個概念了??,好親切。那么接下來看看它都包含了哪些線程(列舉一些主要常駐線程):
1. GUI渲染線程
- 負責渲染瀏覽器界面,解析HTML,CSS,構建DOM樹和RenderObject樹,布局和繪制等。
- 當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行
- 注意,**GUI渲染線程與JS引擎線程是互斥的**,當JS引擎執行時GUI線程會被掛起(相當于被凍結了),GUI更新會被保存在一個隊列中**等到JS引擎空閑時**立即被執行。
2. JS引擎線程
- 也稱為JS內核,負責處理Javascript腳本程序。(例如V8引擎)
- JS引擎線程負責解析Javascript腳本,運行代碼。
- JS引擎一直等待著任務隊列中任務的到來,然后加以處理,一個Tab頁(renderer進程)中無論什么時候都只有一個JS線程在運行JS程序
- 同樣注意,**GUI渲染線程與JS引擎線程是互斥的**,所以如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞。
3. 事件觸發線程
- 歸屬于瀏覽器而不是JS引擎,用來控制事件循環(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開線程協助)
- 當JS引擎執行代碼塊如setTimeOut時(也可來自瀏覽器內核的其他線程,如鼠標點擊、AJAX異步請求等),會將對應任務添加到事件線程中
- 當對應的事件符合觸發條件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理
- 注意,由于JS的單線程關系,所以這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閑時才會去執行)
4. 定時觸發器線程
- 傳說中的`setInterval`與`setTimeout`所在線程
- 瀏覽器定時計數器并不是由JavaScript引擎計數的,(因為JavaScript引擎是單線程的, 如果處于阻塞線程狀態就會影響記計時的準確)
- 因此通過單獨線程來計時并觸發定時(計時完畢后,添加到事件隊列中,等待JS引擎空閑后執行)
- 注意,W3C在HTML標準中規定,規定要求setTimeout中低于4ms的時間間隔算為4ms。
5. 異步http請求線程
- 在XMLHttpRequest在連接后是通過瀏覽器新開一個線程請求
- 將檢測到狀態變更時,如果設置有回調函數,異步線程就**產生狀態變更事件**,將這個回調再放入事件隊列中。再由JavaScript引擎執行。
### 解析URL
輸入URL 后,瀏覽器會進行解析(URL的本質就是統一資源定位符)
URL一般包括幾大部分:
- `protocol`,協議頭,譬如有http,ftp等
- `host`,主機域名或IP地址
- `port`,端口號
- `path`,目錄路徑
- `query`,即查詢參數
- `fragment`,即`#`后的hash值,一般用來定位到某個位置
### 網絡請求都是單獨的線程
每次網絡請求時都需要開辟單獨的線程進行,譬如如果URL解析到http協議,就會新建一個網絡線程去處理資源下載
因此瀏覽器會根據解析出得協議,開辟一個網絡線程,前往請求資源。
- Web 開發筆記
- 從輸入 URL 到頁面加載完成的過程中都發生了什么事情?
- 從瀏覽器接收url到開啟網絡請求線程
- 開啟網絡線程到發出一個完整的http請求
- 從服務器接收到請求到對應后臺接收到請求
- 后臺和前臺的http交互
- http的緩存
- 解析頁面流程
- HTML解析,構建DOM
- CSS解析,構建CSSOM
- 資源外鏈的下載
- CSS的可視化格式模型
- 包含塊(Containing Block)
- 控制框(Controlling Box)
- BFC(Block Formatting Context)
- IFC(Inline Formatting Context)
- 其它
- JS引擎解析過程
- JS的解釋階段
- JS的預處理階段
- JS的執行階段
- 回收機制
- 參考資料
- JavaScript模塊化編程
- AMD
- requireJS
- CommonJS
- UMD
- ES6模塊
- 參考資料
- 使用 JavaScript 實現一門編程語言
- 如何使用 JavaScript 實現一門編程語言(1) —— 前言
- 如何使用 JavaScript 實現一門編程語言(2) —— 編寫一個解析器
- 如何使用 JavaScript 實現一門編程語言(3) —— Input stream
- 如何使用 JavaScript 實現一門編程語言(4) —— Token stream
- 如何使用 JavaScript 實現一門編程語言(5) —— AST
- 如何使用 JavaScript 實現一門編程語言(6) —— Interpreter
- 完整代碼
- 參考資料
- 前端布局概論
- 參考資料
- Windows 筆記
- 錯誤解決
- win10應用商店無法登錄提示0x80070426解決方法
- 使用技巧
- 設置 Hyper-V 和 VMware 共存
- Powershell
- WSL