1. 程式人生 > >【javascript】【非同步事件】怎麼理解js是單執行緒的,但又可以實現非同步程式設計

【javascript】【非同步事件】怎麼理解js是單執行緒的,但又可以實現非同步程式設計

js的非同步事件通常包括以下幾類:
網路請求:ajax請求,服務端響應(隨時發生)
計時器:setTimeOut,setTimeInterval(定時發生)
使用者事件:滑鼠,鍵盤,控制元件(隨時發生)
瀏覽器事件:頁面載入完畢,頁面載入失敗(隨時發生)
以上情況下,程式碼的執行事件都是不確定的,或者不是立刻執行的,不可能由單執行緒來完成

js是單執行緒的,指的是javascript語言是單執行緒的,不支援建立新的執行緒來執行事件
但是瀏覽器可以建立多個js執行緒,從而實現非同步功能
假設把js事件佇列所在的執行緒稱為【事件處理執行緒/主執行緒】,把控制非同步事件執行時機的執行緒稱為【事件觸發執行緒/非同步工作執行緒】
我們來分析下常見的非同步情景下,javascript是如何執行的

ajax請求
主執行緒從事件佇列中取到ajax請求事件,將ajax請求轉給非同步工作執行緒去處理,自己繼續處理佇列中的其它事件
非同步工作執行緒發出ajax請求,並等待服務端響應,當服務端返回響應時,將ajax回撥事件加入到主執行緒的事件佇列中
主執行緒按順序處理事件佇列中的事件,直到遇到ajax回撥事件,將其取出執行

setTimeOut
主執行緒將定時任務交給非同步工作執行緒
非同步工作執行緒開始等待,到達指定時間,將setTimeOut回撥事件加入到主執行緒的事件佇列中
主執行緒按順序處理事件佇列中的事件,直到遇到setTimeOut回撥事件,將其取出執行

setTimeInterval
主執行緒將定時任務交給非同步工作執行緒
非同步工作執行緒開始等待,到達指定時間,將setTimeInterval回撥事件加入到主執行緒的事件佇列中
非同步工作執行緒重複以上過程,每隔一定時間,就向主執行緒的事件佇列加入一個回撥事件
主執行緒按順序處理事件佇列中的事件,每遇到一個setTimeInterval回撥事件,就將其取出執行

從以上過程我們可以發現:
在非同步工作執行緒中,定時是精確的,到達指定時間,就向主執行緒事件佇列加入回撥事件
但是在主執行緒中,因為事件佇列是按順序處理的,必須處理完前面的所有事件,才能執行回撥事件,執行時間完全是不可控的
所以js的定時器是不精確的,設定的時間,只是將回調事件加入到事件佇列中的時間