softare development

JavaScript promise chaining

Learn on the Go. Download the Codeflare Mobile from iOS App Store

1. What is a Promise?

Promise in JavaScript represents a value that may be:

  • Available now
  • Available later
  • Or never available

A promise has three states:

  • Pending
  • Fulfilled (resolved)
  • Rejected

2. What is Promise Chaining?

Promise chaining means linking multiple .then() calls together so that the output of one becomes the input of the next.

👉 Instead of nesting:

doSomething(function(result) {
  doNext(result, function(nextResult) {
    doAnother(nextResult, function(finalResult) {
      console.log(finalResult);
    });
  });
});

👉 You use chaining:

doSomething()
  .then(result => doNext(result))
  .then(nextResult => doAnother(nextResult))
  .then(finalResult => console.log(finalResult))
  .catch(error => console.error(error));

3. How Promise Chaining Works

Each .then():

  • Receives the result of the previous promise
  • Returns a new promise

Example:

const promise = Promise.resolve(5);

promise
  .then(num => num * 2)       // 10
  .then(num => num + 3)       // 13
  .then(num => console.log(num)); // 13

👉 Each step transforms the value and passes it forward.

4. Returning Values vs Returning Promises

✅ Returning a value:

.then(value => value * 2)

Automatically wrapped in a resolved promise.

✅ Returning a promise:

.then(value => {
  return new Promise(resolve => {
    setTimeout(() => resolve(value * 2), 1000);
  });
})

👉 The next .then() waits for it.

5. Real-World Example (API Calls)

fetch('https://api.example.com/user')
  .then(response => response.json())
  .then(user => {
    return fetch(`https://api.example.com/posts/${user.id}`);
  })
  .then(response => response.json())
  .then(posts => console.log(posts))
  .catch(error => console.error(error));

👉 Flow:

  1. Fetch user
  2. Use user ID to fetch posts
  3. Output posts

6. Error Handling in Chaining

Errors propagate down the chain until caught.

doSomething()
  .then(result => {
    throw new Error("Something went wrong");
  })
  .then(() => {
    console.log("This will not run");
  })
  .catch(err => {
    console.error(err.message);
  });

🔸 Important Rule:

👉 A single .catch() can handle errors from all previous .then() calls.

7. Using .finally()

.finally() runs no matter what:

fetchData()
  .then(data => console.log(data))
  .catch(err => console.error(err))
  .finally(() => console.log("Done"));

8. Common Mistakes in Promise Chaining

❌ Not returning a promise

.then(result => {
  fetchData(result); // missing return
})

👉 Fix:

.then(result => {
  return fetchData(result);
})

❌ Nested .then() (anti-pattern)

.then(result => {
  fetchData(result).then(data => {
    console.log(data);
  });
})

👉 Fix:

.then(result => fetchData(result))
.then(data => console.log(data));

9. Parallel vs Sequential Chaining

Sequential (Chaining)

Runs one after another:

task1()
  .then(result => task2(result))
  .then(result => task3(result));

Parallel (Promise.all)

Runs all at once:

Promise.all([task1(), task2(), task3()])
  .then(results => console.log(results));

10. Promise Chaining vs Async/Await

Promise chaining:

getUser()
  .then(user => getPosts(user.id))
  .then(posts => console.log(posts))
  .catch(err => console.error(err));

Async/Await (cleaner):

async function getData() {
  try {
    const user = await getUser();
    const posts = await getPosts(user.id);
    console.log(posts);
  } catch (err) {
    console.error(err);
  }
}

👉 Async/await is just syntactic sugar over promise chaining.

11. Advanced Pattern: Dynamic Chains

const tasks = [1, 2, 3];

tasks.reduce((promise, task) => {
  return promise.then(() => {
    return new Promise(resolve => {
      setTimeout(() => {
        console.log(task);
        resolve();
      }, 1000);
    });
  });
}, Promise.resolve());

👉 Executes tasks one after another.

12. Mental Model (Very Important)

Think of promise chaining like a pipeline:

Input → then() → then() → then() → catch()

Each stage:

  • Processes data
  • Passes it forward
  • Or throws an error

13. Best Practices

✔ Always return values or promises in .then()
✔ Use a single .catch() at the end
✔ Avoid nested .then()
✔ Use .finally() for cleanup
✔ Prefer async/await for readability in complex flows

Final Insight

Promise chaining is what made JavaScript move from messy callbacks to structured async programming. It’s the foundation behind:

  • API calls
  • File handling
  • Database queries
  • Modern frameworks like React, Node.js

Recent Posts

How to Print Documents in JavaScript

Printing a document in JavaScript usually means triggering the browser’s print dialog and controlling what…

12 hours ago

CSS Display Cheatsheet

The display property controls how an element behaves in the layout and how its children are arranged. Access software…

5 days ago

10 JavaScript Habits Destroying Your Code

JavaScript is one of the most flexible programming languages ever created. That flexibility is powerful,…

5 days ago

Linux Steam Locomotive Bash program

What is Steam Locomotive (sl)? Steam Locomotive (sl) is a small terminal program on Unix/Linux systems…

2 months ago

Rate Limiting in Node JS

What is Rate Limiting? Download this article as a PDF on the Codeflare Mobile App…

2 months ago

UI/UX Design — Explained Like You’re 5

Download the Codeflare iOS app and learn on the Go 1. What UI and UX…

3 months ago