1. 程式人生 > 其它 >[JS]任務輪詢

[JS]任務輪詢

JavaScript 是單執行緒的,它不像 Java 那樣新開啟一個執行緒執行任務。如果 JavaScript 要同時執行多個任務,需採取排隊的方式實現。

前言

常常會聽到單執行緒和多執行緒這兩個名詞,單執行緒即一個時間段內程式從上到下執行任務,多執行緒即一個時間段內程式同時執行多個任務。

然而 JavaScript 是單執行緒的,它不像 Java 那樣新開啟一個執行緒執行任務。如果 JavaScript 要同時執行多個任務,需採取排隊的方式實現。

任務佇列

在 JavaScript 中,可以將任務分為兩種,一種是同步任務,另一種是非同步任務。同步任務指的是,在主執行緒上排隊執行的任務,每個任務從上到下依次執行;非同步任務指的是任務不進入主執行緒執行,而是進入到任務佇列中排隊。只有當主執行緒上的所有同步任務執行完畢之後,主執行緒才會讀取任務佇列,開始執行非同步任務。

如果前一個任務耗時很長,後一個任務不能一直等待。特別是對於長時間執行的任務,其他的任務就不能及時得到執行。對於這類情況,JavaScript 在主執行緒執行完所有的任務之後,再去讀取任務佇列上的非同步任務。

在主執行緒中有兩個任務需要被執行,非同步任務會進入到任務佇列中等待主執行緒將同步任務執行完成之後再開始執行任務佇列中的非同步任務。所以,最後的執行結果是 hello javascript 在 hello async javascript 之前。

事件迴圈

主執行緒中的所有同步任務執行完畢,再讀取任務佇列中的非同步任務,這個過程是不斷迴圈的。因此,這種執行機制稱為事件迴圈(Event Loop)。

在非同步任務中,任務被分為兩種,即巨集任務(macrotask)和微任務(microtask)。微任務的優先順序比巨集任務的優先順序高,所以主執行緒讀取任務佇列中的非同步任務時,會優先讀取微任務。

如上圖,紅色背景的任務是一個非同步任務,它需要等待主執行緒的綠色背景的任務被執行完畢之後,主執行緒才會執行非同步任務中的程式碼。

舉例,直觀地體驗巨集任務和微任務在優先度上的區別:

如上圖,Promise 屬於非同步任務中的微任務,它優先於 setTimeout 巨集任務。主執行緒任務先執行,然後進入到任務佇列,先執行微任務,然後再執行巨集任務。