# Event loop: microtasks and macrotasks
Browser JavaScript execution flow, as well as in Node.js, is based on an *event loop*.
Understanding how event loop works is important for optimizations, and sometimes for the right architecture.
In this chapter we first cover theoretical details about how things work, and then see practical applications of that knowledge.
## Event Loop
The concept of *event loop* is very simple. There's an endless loop, when JavaScript engine waits for tasks, executes them and then sleeps waiting for more tasks.
1. While there are tasks:
- execute the oldest task.
2. Sleep until a task appears, then go to 1.
That's a formalized algorithm for what we see when browsing a page. JavaScript engine does nothing most of the time, only runs if a script/handler/event activates.
A task can be JS-code triggered by events, but can also be something else, e.g.:
- When an external script `
```
...But we also may want to show something during the task, e.g. a progress bar.
If we use `setTimeout` to split the heavy task into pieces, then changes are painted out in-between them.
This looks better:
```html run
```
Now the `` shows increasing values of `i`, a kind of a progress bar.
## Use case: doing something after the event
In an event handler we may decide to postpone some actions until the event bubbled up and was handled on all levels. We can do that by wrapping the code in zero delay `setTimeout`.
In the chapter
we saw an example: a custom event `menu-open` is dispatched after the "click" event is fully handled.
```js
menu.onclick = function() {
// ...
// create a custom event with the clicked menu item data
let customEvent = new CustomEvent("menu-open", {
bubbles: true
/* details: can add more details, e.g. clicked item data here */
});
// dispatch the custom event asynchronously
setTimeout(() => menu.dispatchEvent(customEvent));
};
```
The custom event is totally independent here. It's dispatched asynchronously, after the `click` event bubbled up and was fully handled. That helps to workaround some potential bugs, that may happen when different events are nested in each other.
## Microtasks
Along with *macrotasks*, described in this chapter, there exist *microtasks*, mentioned in the chapter .
There are two main ways to create a microtask:
1. When a promise is ready, the execution of its `.then/catch/finally` handler becomes a microtask. Microtasks are used "under the cover" of `await` as well, as it's a form of promise handling, similar to `.then`, but syntactically different.
2. There's a special function `queueMicrotask(func)` that queues `func` for execution in the microtask queue.
After every *macrotask*, the engine executes all tasks from *microtask* queue, prior to running any other macrotasks.
**Microtask queue has a higher priority than the macrotask queue.**
For instance, take a look:
```js run
setTimeout(() => alert("timeout"));
Promise.resolve()
.then(() => alert("promise"));
alert("code");
```
What's the order?
1. `code` shows first, because it's a regular synchronous call.
2. `promise` shows second, because `.then` passes through the microtask queue, and runs after the current code.
3. `timeout` shows last, because it's a macrotask.
**There may be no UI event between microtasks.**
Most of browser processing is macrotasks, including processing network request results, handling UI events and so on.
So if we'd like our code to execute asynchronously, but want the application state be basically the same (no mouse coordinate changes, no new network data, etc), then we can achieve that by creating a microtask with `queueMicrotask`.
Rendering also waits until the microtask queue is emptied.
Here's an example with a "counting progress bar", similar to the one shown previously, but `queueMicrotask` is used instead of `setTimeout`. You can see that it renders at the very end, just like the regular code:
```html run
```
So, microtasks are asynchronous from the point of code execution, but they don't allow any browser processes or events to stick in-between them.
## Summary
The richer event loop picture may look like this:

The more detailed algorithm of the event loop (though still simplified compare to the [specification](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model)):
1. Dequeue and run the oldest task from the *macrotask* queue (e.g. "script").
2. Execute all *microtasks*:
- While the microtask queue is not empty:
- Dequeue and run the oldest microtask.
3. Render changes if any.
4. Wait until the macrotask queue is not empty (if needed).
5. Go to step 1.
To schedule a new macrotask:
- Use zero delayed `setTimeout(f)`.
That may be used to split a big calculation-heavy task into pieces, for the browser to be able to react on user events and show progress between them.
Also, used in event handlers to schedule an action after the event is fully handled (bubbling done).
To schedule a new microtask:
- Use `queueMicrotask(f)`.
- Also promise handlers go through the microtask queue.
There's no UI or network event handling between microtasks: they run immediately one after another.
So one may want to `queueMicrotask` to execute a function asynchronously, but also with the same application state.