Browser reads and runs a JavaScript file, the synchronous tasks written in the file immediately become in-mid-execution task, setTimeout callbacks become macrotasks, and promise callbacks become microtasks. Everything is good.
I thought I mastered the JavaScript Event Loop until I met requestAnimationFrame
.
@T.J. Crowder provided me with the following code snippet.
const messages = [];
setTimeout(() => {
// Schedule a microtask
Promise.resolve().then(() => {
log("microtask");
});
// Schedule animation frame callback
requestAnimationFrame(() => {
log("requestAnimationFrame");
});
// Schedule a macrotask
setTimeout(() => {
log("macrotask");
}, 0);
// Schedule a callback to dump the messages
setTimeout(() => {
messages.forEach(msg => {
console.log(msg);
});
}, 200);
// Busy-wait for a 10th of a second; the browser will be eager to repaint when this task completes
const stop = Date.now() + 100;
while (Date.now() < stop) {
}
}, 100);
function log(msg) {
messages.push(Date.now() + ": " + msg);
}
- Chrome: microtask, requestAnimationFrame, macrotask
- Firefox: microtask, macrotask, requestAnimationFrame
The spec doesn't say whether that can happen between the completion of a macrotask and the processing of its scheduled microtasks, or only between macrotasks. So presumably that can vary browser to browser.
But in both Chrome and Firefox, microtasks are always executed before requestAnimationFrame
callbacks. My questions below are based on this observation.
**Q1: **
Even though the browser has no repaint work, will the requestAnimationFrame's callback be executed at the refresh rate (default 60 per second)?
**Q2: **
Below is from https://developers.google.com/web/fundamentals/performance/rendering/debounce-your-input-handlers
The only way to guarantee that your JavaScript will run at the start of a frame is to use
requestAnimationFrame
.
Too heavy in-mid-execution task will lag the browser, cause the frame interval exceed 16.66ms, block frames from completing.
Does the word 'guarantee' mean that the microtasks will be in-mid-execution immediately the current JS stack becomes empty, hence block the current frame from completing (if the microtask is also too heavy)?