FSM Full Stack Masterclass
Platform under construction
JavaScript course badge

Async JavaScript

Advanced

Event Loop

The event loop coordinates synchronous code, queued tasks and promise microtasks.

console.log("A");
setTimeout(() => console.log("C"), 0);
Promise.resolve().then(() => console.log("B"));

Async JavaScript

The event loop decides when queued code gets a turn.

JavaScript runs synchronous code first. While that code is running, no other JavaScript can interrupt it.

Timers and events queue tasks. Promise callbacks queue microtasks, which run after the current synchronous code and before the next task.

This ordering explains why setTimeout with 0 milliseconds still runs after current code and after promise microtasks.

Call stack

Currently running synchronous JavaScript.

Task queue

Timers, events and other task callbacks.

Microtask queue

Promise callbacks and queueMicrotask.

Render opportunity

The browser can update the screen between work.

Examples

Async code should show state, handle failure and avoid stale results.

Predict order deliberately

console.log("sync");
Promise.resolve().then(() => console.log("microtask"));
setTimeout(() => console.log("task"), 0);

Assuming timeout zero means now

setTimeout(runNow, 0);

// It runs later, after current code and microtasks.

Code patterns

Reusable examples for quick reference.

These examples are the async patterns you will reuse: timers, promises, composition, await, fetch and cancellation.

Synchronous first

Runs immediately.

console.log("first");
console.log("second");

Timer task

Runs in a future task.

setTimeout(() => console.log("timer"), 0);

Promise microtask

Runs before the next timer task.

Promise.resolve().then(() => console.log("microtask"));

queueMicrotask

Queue a microtask explicitly.

queueMicrotask(() => updateAfterCurrentCode());

Rules that matter

Make time visible in your code.

Async JavaScript is easier when every operation has clear pending, success, failure and cancellation behavior.

Synchronous code runs first

The current stack must finish.

Microtasks run before the next task

Promise callbacks have priority over timers.

Timers are not exact clocks

They wait for the stack and browser scheduling.

Long tasks block rendering

Heavy synchronous work freezes the page.

Use small chunks for heavy work

Give the browser chances to respond.

Do not depend on accidental timing

Make ordering explicit with awaited promises.

Production thinking

Reliable async code is what makes modern interfaces feel fast instead of fragile.

Why does this matter?

The event loop explains async ordering bugs that otherwise feel random.

Accessibility

Long synchronous tasks can block keyboard input, focus changes and screen-reader updates.

Production note

Production performance work often starts by finding long tasks that block the event loop.

SEO note

Client-rendered pages need JavaScript to complete reliably; event-loop blocking delays rendering.

Live code lab

Change the HTML, CSS or JavaScript and run the result.

The preview runs inside an isolated iframe. The JavaScript is placed inside the HTML editor for now, so every example stays together and remains easy to understand.

Mini assignment

Try this now.

  • Move the timer before the promise and predict the result.
  • Add queueMicrotask.
  • Add a second Promise.then callback.

Practice assignment

Do this before moving to the next topic.

  1. Write sync code.
  2. Queue a timer.
  3. Queue a promise microtask and predict order.

Try it yourself

Predict execution order

Live preview

Self-check

Before you continue, prove that you understand Event Loop.

Advanced

If you can explain when the code runs, how it fails and what happens if it becomes irrelevant, you understand the async model.

  1. Can you explain the call stack?
  2. Can you explain task queue?
  3. Can you explain microtasks?
  4. Can you explain why timeout zero is not immediate?
  5. Can you explain how long tasks affect UI?

Senior audit upgrade

Extra production context for Event Loop.

Event loop model

Async JavaScript feels clearer when you separate the call stack, microtasks, rendering and later tasks.

call stack
  -> microtasks (promises)
  -> browser may render
  -> tasks (timers, events)
  -> repeat