理解JS異步操作

參考文章:

  1. 阮一峯ES5教程:異步操作 —— 理解異步操作的基本模式和控制流程,瞭解定時任務的實現,Promise的用法
  2. 前端需要了解的瀏覽器原理(佔坑)
  3. Inside look at modern web browser (part 1) —— 該系列文章一共4節,詳細介紹了瀏覽器的工作原理。建議先看part1,然後看過參考文章4後,還想要更加深入全面地瞭解瀏覽器再看part2-4。
  4. 瀏覽器的工作原理:新式網絡瀏覽器幕後揭祕 —— HowBrowsersWork中譯版,看完可瞭解瀏覽器的基本組件和呈現引擎的工作流程

 

最開始通過看ES5教程瞭解JS異步操作時,理解了JS的單線程模型和事件循環機制,教程中也介紹了實現JS異步操作的方法。但是我還是一頭霧水,爲什麼需要異步操作?怎麼劃分異步操作和同步操作?應該在哪裏進行異步操作?我腦中都是模糊的概念。後來我發現我就是少根筋,我只是需要了解一下異步操作的使用場景和通常的異步任務。

 

注意:JS層面的異步和操作系統層面的異步(涉及進程線程併發)是有所區別的,建議分開看待,不易混淆。

 

一、JS的單線程模型和事件循環機制

當我們談論JS層面的異步時,不得不談JS單線程模型和事件循環機制。這是JS異步概念的來源。

JS的單線程模型意味着,在執行JS時只有一個主線程,每個任務必須順序執行。如果當前任務執行時間過長,會導致接下來的所有任務都處於阻塞狀態,進而導致瀏覽器卡死等我們不希望看到的狀況。爲了解決這一問題,事件循環機制(Event Loop)被髮明出來。

事件循環機制中,負責執行JS腳本的單線程我們稱爲主線程,在內存中表現爲一個執行棧,JS只通過主線程執行任務。異步任務被掛起,存儲在堆中,當異步任務準備就緒,它對應的事件便進入任務隊列。主線程首先執行同步任務,然後查看任務隊列是否有就緒的異步任務(或者時間到了的異步任務),調用相應的回調函數執行,直到任務隊列爲空。至此即完成一個事件循環。如下圖所示。

                                                               

                                                          

 關於JS的事件循環機制更詳細的資料可以參考MDNES5教程

 

 二、異步任務

異步任務指的是被JS引擎放在一邊,不進入主線程而進入任務隊列的任務。有時,什麼任務應被定義爲異步任務,這是由開發者決定的(比如你也可以把Ajax設爲同步任務)。常見的異步任務主要有3類:

  • 網絡請求(Ajax)
  • 事件觸發(onclick | onchange etc.)
  • 定時函數(setTimeout | setInterval)

這些異步操作是由瀏覽器內核呈現引擎進行執行的。針對不同類型的異步任務,通常會開不同的線程執行(如事件觸發線程、定時器觸發線程(Timer)、異步http請求線程)。

 

三、微任務(microtask)與宏任務(macrotask)

處理異步任務的方法不同,JS中的任務還可分爲:微任務和宏任務。微任務指的是在本輪事件循環中執行的異步任務,宏任務則指同步任務和下輪事件循環之後執行的異步任務。

微任務:Promise

宏任務:同步任務,定時任務(setTimeout | setInterval)

 

四、如何實現異步

我根據不同的異步場景,對相應的解決方案進行總結。

網絡請求

在JS腳本中進行網絡請求,即AJAX請求。

在瀏覽器呈現頁面的過程中,當HTML解析器碰到<script>的時候,HTML文檔的解析工作會暫停,先執行腳本。也可以將腳本標記爲defer,在HTML文檔解析完成後再執行。HTML5中增加了一個選項可標爲異步,由其他線程解析和執行。(overview of the parsing model

解析到</script>時,會根據腳本中對DOM結構的操作調用樹構造階段,重新調整DOM樹。因此<script>腳本通常放在HTML文檔下方最後處理,避免反覆修改或者產生我們不想要的效果。

1、XMLHttpRequest和AJAX

2、Promise和AJAX

Promise對象使得能夠通過鏈式寫法處理回調。它可以處理任何異步操作而不僅限於AJAX。

3、jQuery和AJAX

使用jQuery的相關對象處理AJAX不需要考慮瀏覽器問題,使得代碼更簡化。jQuery可以看做一個JavaScript更上一層的封裝,AJAX的本質還是不變的。

jQuery在全局對象jQuery(即$)中綁定了ajax()函數來處理AJAX請求。jQuery中還存在jqXHR對象用鏈式寫法處理回調。

4、Window.fetch

Fetch API 提供了請求資源的接口(包括網絡資源),並返回一個Promise對象。

5、Ajxos等庫

總結:Ajax本質不變,實現它的方式多種多樣。

事件觸發

定時任務

定時任務通常使用setTimeout()、setInterval() 兩個方法實現。

(施工中)

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章