Promise vs Async/Await

explore what Promises and async/await are, how they work under the hood, how their execution differs in the event loop

YASH PATEL1/31/20264 min read34 views
JavaScriptAsynchronous Programming
Promise vs Async/Await

Whether you’ve worked with Promises and async/await or not, you might have wondered: What are they, and how do they differ?

Let’s dive in and understand

JavaScript is known for its asynchronous and non-blocking nature. Promises and async/await are key features that enable this behavior, and they are closely related.

Promise

A Promise is an object representing the eventual completion (or failure) of an asynchronous operation. It has three states:

  1. Pending – the initial state, not yet fulfilled or rejected
  2. Fulfilled – the operation completed successfully
  3. Rejected – the operation failed

A promise is said to be settled if it is either fulfilled or rejected (not pending). There is no race conditions between them and You can attach handlers to promises using the .then() method. Promises can also be chained, so one promise can depend on the result of another.

promises-image

for handling of fulfillment and rejection it take 2 values in then()

  • The first argument of .then() handles fulfillment.
  • The second argument handles rejection.
  • .catch() can be used to handle any errors.
1const myPromise = new Promise((resolve, reject) => {
2 setTimeout(() => {
3 resolve("foo");
4 }, 300);
5});
6
7myPromise
8 .then(handleFulfilledA, handleRejectedA);

Async/Await

async/await is syntatic sugar on top of promises means you declare a function async and it create a asyncFunction object and it return a new promise which will be resolved by a return value by the async function it can contain one or more await expression and it makes promise returning function synchronus by suspending execution until the returned promise is fullfilled or reject and resolved alue is treated as return of await expression

async function always return a promise if return value of async function is not promise then it will implicity wrapped in a promise

example

1async function run() {
2 return 1;
3}
4
5// Equivalent to
6function run() {
7 return Promise.resolve(1);
8}
9

An async function always returns a Promise. Even if you return a plain value, it’s automatically wrapped in Promise.resolve().

so we can split the body of async function into no of await expression and if doesn’t contain await expression then it will run as synchronously and if it contains await expression then it will complete asynchronously

1async function run() {
2 const result = await fetchData(); // pauses until fetchData promise resolves
3 console.log(result);
4}
5

in above code you can see first line is await expression and when it runs then it treated as pending promise and after that all statement act as then callback so whenever after some time it gets fulfilled or rejected then it executes next or returns the value

Execution

let’s talk about how both’s execution works

Promise - Promises are directly executed on the event loop. The then() method is added to the microtask queue. Microtasks are executed after the current task completes but before the next task is scheduled.

Async/Await - Async functions are compiled into Promise-based code by the JavaScript engine. The await keyword pauses the execution of the async function until the Promise resolves or rejects. The paused execution is resumed when the Promise is settled.

Performance

  • The performance difference between Promises and async/await is usually minimal.
  • Async functions have a tiny overhead due to pausing and resuming execution at await points.
  • If your code has fewer await expressions or mostly runs in parallel, using Promises directly can slightly reduce overhead.
  • In real-world applications, network or I/O delays dominate, so this difference is rarely noticeable.

Conclusion

Both Promises and async/await are essential for asynchronous programming.

  • Promises are best suited for parallel tasks and simple async flows.
  • Async/await provides cleaner syntax for complex sequences, making code easier to read and maintain.

Ultimately, the choice depends on:

  • Readability – async/await is often easier to understand
  • Performance – Promises can be slightly more efficient in tight loops or micro-optimized code
  • Code structure – async/await is excellent for sequential async operations