DEV Community

TusharShahi
TusharShahi

Posted on

1

UI Blocking behaviour: microtasks vs macrotasks

Can you find the difference between the two code snippets below:

function handleClick1() {
     setTimeout(handleClick1, 0);
}

function handleClick2() {
     Promise.resolve().then(handleClick2);
}
Enter fullscreen mode Exit fullscreen mode

If you are not able to identify the implications of choosing one over the other, then this blog post will teach you something new.

Background

setTimeout is for scheduling a callback after a certain amount of time. Promise.resolve().then will do the same thing effectively, but internally both are different. The latter returns a promise, that is already resolved. Calling then(callback) on that promise will schedule callback to be executed.

So both the above functions call themselves recursively with minimal delay. The difference is that callback from setTimeout is placed in macrotask queue and a callback from a promise.then() is placed in microtask queue. How the event loop treats items from these two queues is what makes the above 2 code snippets the difference.

Event loop treatment of microtask vs macrotask

All an event loop does is while there are tasks to perform, it performs them and then sleeps and waits for other tasks.

Macrotasks (or simply tasks) include functions responsible for work such as:

  1. Parsing
  2. Reacting to DOM,

among others...

After the execution of a task picked from the task queue, the event loop performs a microtask checkpoint. The algo for which is something like:

While microtask queue is not empty, pick the oldest task from microtask queue and execute it.
Enter fullscreen mode Exit fullscreen mode

What this means is that if a microtask enqueues another microtask that task will be executed before the next macrotask. And since UI rendering is a macrotask, it will never be executed by the event loop.

Here is a demo for the above: JS Bin demo. An infinite animation is running. If we trigger handleClick1 then we add some processing to the main thread, but the animation still renders correctly. But if we trigger handleClick2 the animation stops.

I have added the variable totalCount, so we can break before the page crashes. But what is noticeable is that once the microTask loop is started, the UI becomes unresponsive for some time.. Because tasks like rendering, reacting to DOM etc. will only be executed after the microtask queue is empty.

This makes handleClick1 from the above code snippet a safer choice. Hope the blog helped explain one fundamental difference between microtasks and macrotasks.

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️