Why Use .then() When Async/Await Is Cleaner?

dev.to

series: JavaScript Deep Dives

If you ask any modern JavaScript developer how to handle asynchronous code, they will almost certainly tell you to use async/await. It reads like synchronous code, eliminates callback nesting, and works beautifully with standard try/catch blocks.

So why does .then() still exist? Is it just legacy technical debt, or does it actually have legitimate use cases in 2026?

Let’s look at why .then() is still a vital tool in your JavaScript toolkit.


1. Fire-and-Forget Operations (Non-Blocking Tasks)

Sometimes you want to trigger an asynchronous action in the background, but you don't want to pause your main function while waiting for it to finish.

Imagine a user clicks a button. You need to track an analytics event (async) and immediately redirect them to their dashboard.

The Async/Await Approach:

If you use await, you force the user to wait for the analytics server to respond before they get redirected:

async function handleLogin() {
  // The user is stuck waiting here!
  await trackAnalytics("User Logged In"); 

  navigateToDashboard(); 
}
Enter fullscreen mode Exit fullscreen mode

The .then() Solution:

With .then(), you kick off the analytics call in the background and immediately move the user forward:

function handleLogin() {
  // Fires in the background, non-blocking
  trackAnalytics("User Logged In").then(() => console.log("Logged!")); 

  // Runs instantly!
  navigateToDashboard(); 
}
Enter fullscreen mode Exit fullscreen mode

2. Cleaner Inline Pipelines (Functional Programming)

If you love clean, functional programming pipelines, .then() allows you to chain pure functions together cleanly without declaring temporary variables.

// Quick, readable data pipeline
fetchUserData()
  .then(extractEmail)
  .then(validateDomain)
  .then(sendWelcomeEmail);
Enter fullscreen mode Exit fullscreen mode

To do this with async/await, you have to assign a new variable to every single step, which creates a lot of visual boilerplate:

async function pipeline() {
  const user = await fetchUserData();
  const email = extractEmail(user);
  const isValid = validateDomain(email);
  return sendWelcomeEmail(isValid);
}
Enter fullscreen mode Exit fullscreen mode

3. Quick Top-Level Scripts

While modern environments support "Top-Level Await" in ES modules, you still cannot use await at the root level of older Node.js scripts or legacy CommonJS files without wrapping everything in an Immediately Invoked Function Expression (IIFE).

The Async/Await Wrapper:

(async () => {
  const data = await database.connect();
  console.log(data);
})();
Enter fullscreen mode Exit fullscreen mode

The .then() Alternative:

database.connect().then(console.log);
Enter fullscreen mode Exit fullscreen mode

For a quick script or a scratchpad file, .then() gets the job done with zero boilerplate.


The Verdict: Use the Right Tool

async/await and .then() are not enemies—async/await is literally built on top of promises.

  • Use async/await for 90% of your code, especially linear workflows, complex API fetches, and heavy error handling.
  • Use .then() when you need background tasks, quick one-liners, or functional data pipelines.

What’s your preference? Do you still use .then() in your projects, or have you completely migrated to async/await? Let me know in the comments below! 👇

Source: dev.to

arrow_back Back to News