The Surprising Truth about JavaScript Promises

Vijay Rangan
2 min readFeb 5, 2024
Photo by Mohammad Rahmani on Unsplash

As developers, we often work with promises and callbacks in our code. While they may seem similar at first glance, there are some important differences to keep in mind. In this article, we will explore these differences and gain a deeper understanding of how promises and callbacks work.

Through an execution order experiment, we will examine the task queue versus the microtask queue and how they impact the behavior of callback functions and promises. By the end of this article, we will have a clear understanding of the promise mechanism and the microtask queue, as well as how they differ from callback functions and the task queue.

Key Takeaways

  • Promises and callbacks have important differences in how they execute in code.
  • The microtask queue runs before the task queue, impacting the order of execution.

Execution Order Experiment

I setup an experiment to observe the execution order of promises and callbacks. The sample code below sets up a promise that logs a value and a callback function that uses setTimeout to log the same value.

const promise = new Promise(resolve => {
resolve('promise value');
});

setTimeout(() => {
console.log('setTimeout value');
}, 0);

promise.then(value => {
console.log(value);
});

At first glance, it may seem that the order of execution would be the same regardless of the order of the code. However, the order of execution is actually dependent on the type of queue being used.

Depending on the type of async mechanism you use, one of two queues are used internally

  1. Microtask queue — or —
  2. Task queue (aka Macrotask queue)

The main difference between the microtask queue and the task queue is that every task that’s been queued up in the microtask is run first, irrespective of how many items are there in the task queue.

To test this, I switched the order of the code and ran it again:

setTimeout(() => {
console.log('setTimeout value');
}, 0);

const promise = new Promise(resolve => {
resolve('promise value');
});

promise.then(value => {
console.log(value);
});

The result is still the same. From this it is clear that promises use the microtask queue, while callbacks like setTimeout use the task queue. This is why the setTimeout function always runs after the Promise.

Understanding this difference between the task queue and the microtask queue is important when working with promises and callback functions. It can help prevent unexpected behavior and ensure that our code runs as intended.

If you’re the kind of person that likes consuming tech content via videos, you can find a video of this on my YouTube channel.

YouTube link : The Surprising Truth about JavaScript Promises

If you liked this article and you learned something, don’t be shy… show some love with a 👏 😀

Until next time…

--

--