DEV Community

Cover image for The Surprising Truth about Promises
Vijay Rangan
Vijay Rangan

Posted on

The Surprising Truth about Promises

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.

The 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);
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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…

Top comments (2)

Collapse
 
oculus42 profile image
Samuel Rouse

HI Vijay! Thanks for the article! It provides some simple, clear information about execution order in JavaScript.

Also, thanks for bringing this content over from Medium, but it appears some of the formatting, including the link to your YouTube video, was lost in the transfer.

Collapse
 
vjrngn profile image
Vijay Rangan

Thanks @oculus42 for the heads up! Really appreciate it :) Fixed the post 👍🏻