在 事件回圈 期間的某個時刻,運行時會從最先進入佇列的訊息開始處理佇列中的訊息,被處理的訊息會被移出佇列,并作為輸入引數來呼叫與之關聯的函式,正如前面所提到的,呼叫一個函式總是會為其創造一個新的堆疊幀,函式的處理會一直進行到執行堆疊再次為空為止;然后事件回圈將會處理佇列中的下一個訊息(如果還有的話),
"執行至完成"
每一個訊息完整地執行后,其它訊息才會被執行,這為程式的分析提供了一些優秀的特性,包括:當一個函式執行時,它不會被搶占,只有在它運行完畢之后才會去運行任何其他的代碼,才能修改這個函式操作的資料,這個模型的一個缺點在于當一個訊息需要太長時間才能處理完畢時,Web 應用程式就無法處理與用戶的互動,例如點擊或滾動,為了緩解這個問題,瀏覽器一般會彈出一個“這個腳本運行時間過長”的對話框,一個良好的習慣是縮短單個訊息處理時間,并在可能的情況下將一個訊息裁剪成多個訊息,
函式 setTimeout 接受兩個引數:待加入佇列的訊息和一個時間值(可選,默認為 0),這個時間值代表了訊息被實際加入到佇列的最小延遲時間,如果佇列中沒有其它訊息并且堆疊為空,在這段延遲時間過去之后,訊息會被馬上處理,但是,如果有其它訊息,setTimeout 訊息必須等待其它訊息處理完,因此第二個引數僅僅表示最少延遲時間,而非確切的等待時間,
零延遲
零延遲并不意味著回呼會立即執行,以 0 為第二引數呼叫 setTimeout 并不表示在 0 毫秒后就立即呼叫回呼函式,
其等待的時間取決于佇列里待處理的訊息數量,在下面的例子中,"這是一條訊息" 將會在回呼獲得處理之前輸出到控制臺,這是因為延遲引數是運行時處理請求所需的最小等待時間,但并不保證是準確的等待時間,
setTimeout 需要等待當前佇列中所有的訊息都處理完畢之后才能執行,即使已經超出了由第二引數所指定的時間,
JS執行順序
- JS是從上到下一行一行執行,
- 如果某一行執行報錯,則停止執行下面的代碼,
- 先執行同步代碼,再執行異步代碼
事件回圈的執行程序
- 同步代碼,呼叫堆疊執行后直接出堆疊
- 異步代碼,放到Web API中,等待時機,等合適的時候放入回呼佇列(callbackQueue),等到呼叫堆疊空時eventLoop開始作業,輪詢
- 微任務執行時機比宏任務要早
- 微任務在DOM渲染前觸發,宏任務在DOM渲染后觸發
宏任務(Macro tasks)主要包含:script( 整體代碼)、setTimeout、setInterval、I/O、UI 互動事件、setImmediate(Node.js 環境)、Ajax、DOM事件
微任務(Microtasks)主要包含:Promise、MutaionObserver、process.nextTick(Node.js 環境)、async/await
同步任務與異步任務
同步和異步任務分別進入不同的執行環境,同步的進入主執行緒,即主執行堆疊,異步的進入任務佇列,主執行緒內的任務執行完畢為空,會去任務佇列讀取對應的任務,推入主執行緒執行, 上述程序的不斷重復就是我們說的 Event Loop (事件回圈),
堆疊stack:函式呼叫形成了一個由若干幀組成的堆疊 堆heap:物件被分配在堆中,堆是一個用來表示一大塊(通常是非結構化的)記憶體區域的計算機術語, 佇列:一個 JavaScript 運行時包含了一個待處理訊息的訊息佇列,每一個訊息都關聯著一個用以處理這個訊息的回呼函式轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/517785.html
標籤:JavaScript
上一篇:SWIFTUI-如果用戶已經在ScrollView的頂部,如何禁用向上滾動,反之亦然
下一篇:事件回圈Event Loop
