JS / 03.07.2023 / Alex

Event Loop

Hello there, code enthusiast! Let's dive into a captivating part of JavaScript's core - the Event Loop. This knowledge can not only boost your coding skills but also your income after acing those job interviews! So, get ready!

How Does it Work?

When JavaScript initiates an asynchronous operation, like a network request, it doesn’t wait around. It continues executing the rest of the code. Once the response comes back, the callback function is queued. The Event Loop continually checks if the call stack is empty, and if so, it processes the first task from the queue. This way, JavaScript isn't blocked by async operations.

Event Loop

The Event Loop is like the heart of JavaScript, continuously pumping events and messages.

The Event Loop plays a vital role in handling:

  • Promises
  • Timers
  • User events

Do note that because of the Event Loop, timers may not fire at the exact time you specify. User interactions, network requests, and other events are also directed by the Event Loop.

Promises

Promises are a JavaScript language-level feature that debuted in ECMAScript 6 (ES6). They brought a new way to handle async operations.

Interestingly, each Promise has its private microtask queue that trumps the regular task queue. Hence, the callbacks for .then or .catch of a Promise are executed as soon as the current stack is cleared, even before any task in the regular queue.

Timers

Unlike Promises, timers (setTimeout and setInterval) are not part of the JavaScript language. They are Web APIs offered by the browser.

When you set a timer, the browser starts it. Once it expires, the callback function is queued. But, if the JavaScript thread is busy, the callback must wait for its turn. So, timers in JavaScript don't assure execution at the precise time specified.

Microtasks vs. Macrotasks

The Event Loop's task queue is broadly divided into:

Macrotasks:

  • Scripts
  • User events
  • setTimeout, setInterval, setImmediate operations

Microtasks:

  • process.nextTick
  • Promises
  • Object.observe
  • MutationObserver

The Event Loop gives priority to microtasks over macrotasks, ensuring promises resolve as swiftly as possible, keeping up JavaScript's non-blocking nature.

Event Loop

Here's how the Event Loop works:

  1. JavaScript starts by running the entire script as a callstack (a macrotask).
  2. After the initial script finishes, JavaScript checks the microtask queue. Any microtasks queued up during the initial script execution get processed.
  3. If a microtask schedules another microtask, it gets added to the queue, and the process continues until the microtask queue is empty.
  4. After all microtasks are done, control goes back to the Event Loop. It checks for any other macrotasks in the queue.
  5. After each macrotask, JavaScript checks the microtask queue again and processes all microtasks.

Example

Try out this code to see the Event Loop in action:

console.log('1');

setTimeout(function log5() {
  console.log('5');
});

var promise = new Promise(function log2(resolve) {
  console.log('2');
  setTimeout(function log6() {
    console.log('6');
    var promiseInsideTimer = new Promise(function log7(resolveInsideTimer) {
      console.log('7');
      resolveInsideTimer(console.log('8'));
    });

    promiseInsideTimer.then(function logUndefined(result) {
      console.log('First undefined:', result);
      resolve(console.log('9'));
    });
  });
});

console.log('3');
promise.then(function logUndefined(result) {
  console.log('Secont undefined:', result);
});
console.log('4');

You'll see this output: 1, 2, 3, 4, 5, 6, 7, 8, First undefined: undefined, 9, Second undefined: undefined.

Useful links

  1. What the heck is the event loop anyway? | Philip Roberts | JSConf EU.
  2. Что такое Event Loop в JavaScript? За 5 минут.
  3. Event Loop от А до Я.