queueMicroTask in JavaScript
In this article, we analyze queueMicroTask function in React source code
React uses queueMicroTask in a file named ReactAct.js. This is a public API, act.
act is a test helper to apply pending React updates before making assertions.
await act(async actFn)
ReactAct.js has a lot of code, let’s narrow down our focus on to queueMicroTask.
Where is queueMicroTask called in ReactAct.js?
queueSeveralMicrotasks
is found at the end of this ReactAct.js file and calls queueMicroTask with a callback and has detailed comment explaining its purpose.
queueSeveralMicrotasks is found to be called in two places:
// Warn if the an `act` call with an async scope is not awaited. In a
// future release, consider making this an error.
queueSeveralMicrotasks(() => {
if (!didAwaitActCall && !didWarnNoAwaitAct) {
didWarnNoAwaitAct = true;
console.error(
'You called act(async () => …) without await. ' +
'This could lead to unexpected testing behaviour, ' +
'interleaving multiple act calls and mixing their ' +
'scopes. ' +
'You should - await act(async () => …);',
);
}
});
// Warn if something suspends but the `act` call is not awaited.
// In a future release, consider making this an error.
if (queue.length !== 0) {
queueSeveralMicrotasks(() => {
if (!didAwaitActCall && !didWarnNoAwaitAct) {
didWarnNoAwaitAct = true;
console.error(
'A component suspended inside an `act` scope, but the ' +
'`act` call was not awaited. When testing React ' +
'components that depend on asynchronous data, you must ' +
'await the result:\n\n' +
'await act(() => …)',
);
}
});
}
Now that we saw how queueMicroTask is used, let’s now understand the definition of queueMicroTask.
queueMicroTask
The queueMicrotask() method of the Window interface queues a microtask to be executed at a safe time prior to control returning to the browser’s event loop.
The microtask is a short function which will run after the current task has completed its work and when there is no other code waiting to be run before control of the execution context is returned to the browser’s event loop.
This lets your code run without interfering with any other, potentially higher priority, code that is pending, but before the browser regains control over the execution context, potentially depending on work you need to complete.
Read more about queueMicroTask at MDN Docs.
Example:
Here’s an example of how microtasks and macrotasks interact with the browser’s execution:
console.log('Synchronous 1'); // 1
Promise.resolve().then(() => {
console.log('Microtask 1'); // 3
});
console.log('Synchronous 2'); // 2
setTimeout(() => {
console.log('Macrotask 1'); // 5
}, 0);
console.log('Synchronous 3'); // 4
Breakdown:
The synchronous code runs first, outputting:
‘Synchronous 1’
‘Synchronous 2’
‘Synchronous 3’
Before the browser gets a chance to handle any pending rendering or macrotasks, the microtask queue is processed:
The Promise.resolve().then(…) callback is added to the microtask queue and is executed right after the synchronous code block is finished, logging:
‘Microtask 1’
After the microtask queue is emptied, the browser regains control and can:
Run macrotasks, like the setTimeout callback, which logs:
‘Macrotask 1’
Final output
Synchronous 1
Synchronous 2
Synchronous 3
Microtask 1
Macrotask 1
About us:
At Think Throo, we are on a mission to teach the advanced codebase architectural concepts used in open-source projects.
10x your coding skills by practising advanced architectural concepts in Next.js/React, learn the best practices and build production-grade projects.
We are open source — https://github.com/thinkthroo/thinkthroo (Do give us a star!)
Up skill your team with our advanced courses based on codebase architecture. Reach out to us at hello@thinkthroo.com to learn more!