Event Loop & Call Stack in JavaScript - Exercise 2

The task queue holds callbacks from operations such as timers and DOM events until the event loop can run them.

setTimeout(() => console.log('task one'), 0);
button.addEventListener('click', () => console.log('event task'));

A microtask is high-priority asynchronous work, commonly created by Promise handlers or queueMicrotask.

queueMicrotask(() => console.log('microtask'));
Promise.resolve().then(() => console.log('promise microtask'));

The Promise handler runs first because the event loop drains microtasks before taking the next task.

setTimeout(() => console.log('timer'), 0);
Promise.resolve().then(() => console.log('promise'));
// promise, timer

JavaScript runs every queued microtask before moving to the next task, including microtasks added by earlier microtasks.

queueMicrotask(() => {
  console.log('first');
  queueMicrotask(() => console.log('second'));
});
setTimeout(() => console.log('timer'), 0);

The code after await pauses and resumes as a Promise microtask, while synchronous code outside the async function can continue.

async function load() {
  console.log('before await');
  await Promise.resolve();
  console.log('after await');
}
load();
console.log('outside');
// before await, outside, after await

The delay is a minimum wait. The callback still waits for the current stack and earlier queued work to finish.

const start = Date.now();
while (Date.now() - start < 100) {}
setTimeout(() => console.log('runs after the blocking loop'), 0);

Each fulfilled handler schedules the next handler as another microtask.

Promise.resolve()
  .then(() => console.log('step one'))
  .then(() => console.log('step two'));
setTimeout(() => console.log('task'), 0);

Synchronous code runs first, then microtasks, then timer or other task callbacks.

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