js中的事件輪詢(event loop)機制


異步任務指的是,不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務可以執行了,該任務才會進入主線程執行。

  1. 所有同步任務都在主線程上執行,形成一個執行棧(execution context stack)。
  2. 主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
  3. 一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務隊列",看看里面有哪些事件。那些對應的異步任務,於是結束等待狀態,進入執行棧,開始執行。
  4. 主線程不斷重復上面的第三步

"任務隊列"是一個先進先出的數據結構,排在前面的事件,優先被主線程讀取。主線程的讀取過程基本上是自動的,只要執行棧一清空,"任務隊列"上第一位的事件就自動進入主線程。但是,由於存在后文提到的"定時器"功能,主線程首先要檢查一下執行時間,某些事件只有到了規定的時間,才能返回主線程。

主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼調用各種外部API,它們在"任務隊列"中加入各種事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。

  • setTimeout(fn,0)
    它在"任務隊列"的尾部添加一個事件,因此要等到同步任務和"任務隊列"現有的事件都處理完,才會得到執行。

  • nodejs
    process.nextTick setImmediate

    process.nextTick方法可以在當前"執行棧"的尾部----下一次Event Loop(主線程讀取"任務隊列")之前----觸發回調函數
    setImmediate方法則是在當前"任務隊列"的尾部添加事件,也就是說,它指定的任務總是在下一次Event Loop時執行,這與setTimeout(fn, 0)很像
    process.nextTick和setImmediate的一個重要區別:多個process.nextTick語句總是在當前"執行棧"一次執行完,多個setImmediate可能則需要多次loop才能執行完。

  • Promise.resolve()
    立即resolve的Promise對象,是在本輪“事件循環”(event loop)的結束時,所以在setTimeout前發生


免責聲明!

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



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