js的異步和單線程


最近,同事之間做技術分享的時候提到了一個問題“js的異步是另開一個線程嗎?”當時為此爭論不休。會后自己查閱了一些資料,對這個問題進行一個自我的分析與總結,有不同意見的希望可以賜教,謝謝!

  js的異步主要有三部分:定時器setTimeout/setInterval;HTTP請求;事件響應。

對於定時器setTimeout/setInterval的異步問題,高程上《高級定時器》(P609)是這樣解釋的:

除了主JavaScript執行進程外,還需要一個在進程下一次空閑時執行的代碼隊列。隨着頁面生命周期推移,代碼會按照執行順序添加入隊列,例如當按 鈕被按下的時候他的事件處理程序會被添加到隊列中,並在下一個可能時間內執行。在接到某個Ajax響應時,回調函數的代碼會被添加到隊列。JavaScript中沒有任何代碼是立即執行的,但一旦進程空閑則盡快執行。定時器對隊列的工作方式是當特定時間過去后將代碼插入,這並不意味着它會馬上執行,只能表示它盡快執行。
定時器對隊列的工作方式是當特定時間過去后將代碼插入,這並不意味着它會馬上執行,只能表示它盡快執行。定時器對隊列的工作方式是,當特定的時間過去后,將代碼插入,注意添加到隊列並不意味着它會馬上執行,而只能說它會盡快執行,設定一個150ms后執行的定時器,不代表150ms后它會馬上執行,它只會表示在150ms后被加入到隊列中,如果這個時間點隊列是空閑的,那么這段代碼就會被執行;其他情況下,代碼可能明顯地等待更長時間才執行。

總結:

  1. Javascript引擎解析是一個單線程的過程,瀏覽器無論在任何時候有且只有一個線程在運行Javascript程序;

  2. 瀏覽器是多線程的,這些線程在內核控制下相互配合以保持同步。在處理js的異步上瀏覽器內核的實現可能有多個進程:Javascript引擎線程、界面渲染線程、瀏覽器事件觸發線程、HTTP請求線程…… 補充 : 這些線程的名字為渲染引擎、網絡、js解析器等 參考自 前端必讀:瀏覽器內部工作原理

  3. Javascript除了一個主線程外,還配有一個代碼隊列,這個隊列用以存放定時器、HTTP請求、事件響應的回調。

所以我對這個流程的理解是這樣的:

  Javascript代碼自上而下執行的,當執行到定時器、或者發送HTTP請求、或者發生用戶交互事件響應時,會自動觸發對應事件(HTTP請求、事件響應),將回調函數儲存到隊列中。Javascript執行完主線程代碼后,會去執行任務隊列,隊列內這個時間點是否有代碼要執行;如果有,則執行隊列中的代碼。

進一步理解——對隊列:

  有細心的會發現,上面的理解沒有加入"定時器",我對此的進一步理解: 有一個現象,Javascript里提供了console.time(name)console.timeEnd(name)可以打印出一段代碼的執行時間。由此,我感覺Javascript每一段代碼的執行都會有記錄一個時間。Javascript會根據這個時間來安排隊列.

  當代碼執行到用戶交互事件時,會傳入回調給隊列,該回調的時間就是事件觸發的時間;當代碼執行到定時器的時候,傳入隊列的回調函數的時間是定時器觸發的時間加上延遲;而HTTP請求傳遞給隊列的回調函數的時間則是其取得數據的時間(我感覺中間可能穿插了一個readyState==4時會重新傳入一個時間,或者可以直接拋去時間,做if判斷,判斷狀態是4時執行);這樣可以根據時間對隊列進行進一步排序,形成一個自上而下的隊列!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM