js的eventloop中的宏任務和微任務理解,實現對setTimout定時器補償

js的eventloop中的宏任務和微任務理解,實現對setTimout定時器補償

寫有關宏任務和微任務的優秀博文有很多已經差不多講的很詳細,寫這邊博客並不是要做一個補充, 大略只是對自己學習理解做一個記錄補充,同時進行分享。有助於輸出推動學習。

外文鏈接:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/?utm_source=html5weekly

event loop(事件循環)

我們js運行是單線程的,所以js的執行事件就需要按照順序排列一項一項執行任務,當執行完成這次的之後就會等待下一次事件隊列執行,如此循環往復就叫 eventLoop

同步&異步任務執行順序

我們都知道js的代碼運行分爲同步和異步,同步代碼不會等待異步代碼執行完畢,而是先執行同步代碼後執行異步代碼。直接看圖:(網上素材)
在這裏插入圖片描述
解釋一下:

1.當一個一個事件循環開始時,同步事件直接放到主線程執行,異步事件放到event table並回調事件, 異步事件執行玩之後需要調用回調的時候,就到event queue中等待真正執行。

2.事件處理機制讀取主線程任務並執行完畢。

3.之後從event queue中讀取回調到主線程的事件執行

也就是說,當異步事件執行完之後回調並不是立即執行的,而是要等待主線程同步任務執行完畢

所以當我們使用setTimeout作爲定時器時,經常會不精確,因爲有可能主線程需要運算很久的話,定時器的回調就會一直等待同步代碼執行完畢

function func() {
	setTimeout(()=> {
		console.log("異步")
	},100)
	/*
		一段需要大量計算的同步代碼... (耗時3s)
	*/
	console.log("同步")
}

//控制檯
同步
異步

這對於抽獎這種需要時間很準確的場景來說,就顯得很嚴重了,所以我們嘗試通過定時器補償的方法來提高精確度

let start = new Date().getTime(),  
    time = 0,  
    before = '0.0';  
function instance()  
{  
    time += 100;  
    before = Math.floor(time / 100) / 10;  
    if(Math.round(before) == before) { before += '.0'; }  
    document.title = before;  
    var diff = (new Date().getTime() - start) - time;  
    setTimeout(instance, (100 - diff));  
}  
setTimeout(instance, 100);  

宏任務&微任務

宏任務和微任務都是異步執行的事件,但是又分執行先後。

宏任務主要包括: 執行script代碼塊,setTimeout,setInterval、setImmediate。

微任務包括: 原生Promise、process.nextTick、Object.observe、 MutationObserver

其中我們最常見的就是 setTimeout,setInterval,Promise這幾個

//代碼
console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

//輸出
script start
script end
promise1
promise2
setTimeout

從上面我們可以看出執行順序是:

同步任務 => Promise回調(微任務) => setTimeout(宏任務)

但是其實真正的執行順序是宏任務先被放到event Table中註冊執行,微任務後被放到event Table中註冊執行,但是最後主線程是從event Queue先取出微服務的回調執行,宏服務的回調後執行。

如圖:(網上素材)
在這裏插入圖片描述

總來的來說了解event loop事件循環處理機制還是很有必要的,讓我們瞭解爲什麼代碼是這樣執行的,可以避免不必要的錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章