0
0
Javascriptprogramming~15 mins

Then and catch methods in Javascript - Deep Dive

Choose your learning style9 modes available
Overview - Then and catch methods
What is it?
Then and catch are methods used with Promises in JavaScript to handle asynchronous operations. The then method runs code when a Promise finishes successfully, while catch runs code if the Promise fails. They help manage tasks that take time, like loading data from the internet, without stopping the rest of the program.
Why it matters
Without then and catch, handling tasks that take time would be messy and confusing, making programs freeze or behave unpredictably. These methods let programs keep running smoothly while waiting for results, improving user experience and reliability. They make it easier to write clear, organized code for things that happen later.
Where it fits
Before learning then and catch, you should understand basic JavaScript functions and how asynchronous code works. After mastering these methods, you can learn about async/await syntax, which builds on Promises for even cleaner asynchronous code.
Mental Model
Core Idea
Then runs code after a successful task, catch runs code if the task fails, both helping manage what happens next in asynchronous operations.
Think of it like...
Imagine ordering food at a restaurant: then is like the waiter bringing your meal when it's ready, and catch is like the waiter telling you if the kitchen ran out of your order.
Promise
  │
  ├─ then(successHandler) ──▶ Runs if task succeeds
  │
  └─ catch(errorHandler) ──▶ Runs if task fails
Build-Up - 7 Steps
1
FoundationUnderstanding Promises Basics
🤔
Concept: Introduce what a Promise is and why it is used.
A Promise is a JavaScript object that represents a task that will finish in the future. It can either succeed (resolve) or fail (reject). Promises help avoid waiting and freezing by letting code run while the task is still working.
Result
You know that Promises are placeholders for future results, not immediate values.
Understanding Promises is key because then and catch only work with these objects to handle future outcomes.
2
FoundationBasic Then Method Usage
🤔
Concept: Learn how to use then to handle successful Promise results.
The then method takes a function that runs when the Promise resolves successfully. This function receives the result of the Promise. For example: const promise = Promise.resolve('Hello'); promise.then(result => console.log(result)); This prints 'Hello' when the Promise finishes.
Result
The console shows: Hello
Knowing then lets you react to success without blocking the program, making asynchronous code easier to manage.
3
IntermediateUsing Catch for Errors
🤔
Concept: Learn how catch handles Promise failures.
The catch method takes a function that runs if the Promise rejects with an error. For example: const promise = Promise.reject('Error happened'); promise.catch(error => console.log(error)); This prints the error message when the Promise fails.
Result
The console shows: Error happened
Using catch prevents unhandled errors and keeps your program from crashing unexpectedly.
4
IntermediateChaining Then and Catch Methods
🤔Before reading on: Do you think catch can handle errors from any previous then in the chain? Commit to your answer.
Concept: Learn how to chain multiple then calls and add catch at the end to handle errors anywhere in the chain.
Promises can chain then methods to run steps in order. If any step fails, catch at the end catches the error: Promise.resolve(5) .then(num => num * 2) .then(num => { throw 'Oops'; }) .catch(error => console.log('Caught:', error)); This prints 'Caught: Oops'.
Result
The console shows: Caught: Oops
Knowing catch handles errors from any previous step helps write safer, cleaner asynchronous code.
5
IntermediateReturning Promises in Then
🤔Before reading on: If a then returns a Promise, does the next then wait for it to finish? Commit to your answer.
Concept: Understand that returning a Promise inside then creates a chain that waits for that Promise to resolve before continuing.
If a then returns a Promise, the next then waits for it: Promise.resolve(10) .then(num => Promise.resolve(num + 5)) .then(result => console.log(result)); This prints 15 after the inner Promise resolves.
Result
The console shows: 15
Understanding this chaining behavior is crucial for sequencing asynchronous tasks correctly.
6
AdvancedError Propagation in Then Chains
🤔Before reading on: If a then throws an error, will catch always catch it? Commit to your answer.
Concept: Learn how errors thrown inside then propagate down the chain until caught by catch.
Errors thrown inside then skip all following then methods until a catch is found: Promise.resolve() .then(() => { throw 'Error in then'; }) .then(() => console.log('This will not run')) .catch(error => console.log('Caught:', error)); Only the catch runs, printing the error.
Result
The console shows: Caught: Error in then
Knowing error propagation prevents silent failures and helps design robust asynchronous flows.
7
ExpertSubtle Differences Between Catch and Then
🤔Before reading on: Can then handle errors if you provide a second function? Is it the same as catch? Commit to your answer.
Concept: Explore how then can take two functions (success and failure), but catch is preferred for error handling due to clearer semantics and chaining behavior.
Then can take two arguments: Promise.reject('Fail') .then( result => console.log('Success:', result), error => console.log('Handled in then:', error) ); But catch is clearer and better for chaining: Promise.reject('Fail') .catch(error => console.log('Handled in catch:', error));
Result
Both print the error, but catch is more readable and chains better.
Understanding this subtlety helps write clearer, more maintainable asynchronous code.
Under the Hood
Promises represent a future value with three states: pending, fulfilled, or rejected. Then and catch register callback functions that the JavaScript engine stores internally. When the Promise settles (fulfills or rejects), the engine runs the appropriate callbacks asynchronously in the microtask queue, ensuring the main program flow is not blocked.
Why designed this way?
Promises and their then/catch methods were designed to replace older callback patterns that caused confusing nested code ('callback hell'). This design allows chaining and centralized error handling, making asynchronous code easier to write and reason about.
┌─────────────┐
│  Promise    │
│ (pending)  │
└─────┬───────┘
      │
      ▼
┌─────────────┐       ┌─────────────┐
│ fulfilled   │──────▶│ then(success)│
└─────────────┘       └─────────────┘
      │
      ▼
┌─────────────┐       ┌─────────────┐
│ rejected    │──────▶│ catch(error) │
└─────────────┘       └─────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does catch only handle errors from the Promise itself, or also from previous then methods? Commit to your answer.
Common Belief:Catch only handles errors from the original Promise rejection, not from errors thrown inside then methods.
Tap to reveal reality
Reality:Catch handles any error thrown in the Promise chain, including inside then methods.
Why it matters:Believing otherwise can cause missed errors and bugs that are hard to find.
Quick: If you don't add catch, will errors in Promises be ignored silently? Commit to your answer.
Common Belief:If you omit catch, errors in Promises are ignored and don't affect the program.
Tap to reveal reality
Reality:Without catch, unhandled Promise rejections cause warnings and can crash the program in some environments.
Why it matters:Ignoring errors leads to unstable programs and poor user experience.
Quick: Can then handle both success and failure equally well? Commit to your answer.
Common Belief:Then can handle both success and failure by passing two functions as arguments, so catch is unnecessary.
Tap to reveal reality
Reality:While then can take two functions, catch is clearer and better for error handling and chaining.
Why it matters:Using then for errors can make code harder to read and maintain.
Quick: Does returning a value inside then immediately run the next then? Commit to your answer.
Common Belief:Returning a value inside then runs the next then immediately, without waiting.
Tap to reveal reality
Reality:Returning a Promise inside then delays the next then until that Promise resolves.
Why it matters:Misunderstanding this causes bugs in sequencing asynchronous tasks.
Expert Zone
1
Errors thrown inside catch handlers propagate down the chain just like in then, so you can chain multiple catch blocks for different error handling.
2
Then and catch always run asynchronously, even if the Promise is already settled, ensuring consistent timing and avoiding unexpected behavior.
3
Using catch at the end of a chain is a best practice to centralize error handling, but intermediate catch blocks can be used to recover and continue the chain.
When NOT to use
Then and catch are less readable for complex asynchronous flows compared to async/await syntax, which uses try/catch blocks and looks more like synchronous code. For very simple callbacks, direct callback functions might be simpler.
Production Patterns
In real-world code, then and catch are used to handle API calls, file operations, and timers. Developers often chain multiple then calls for sequential steps and use catch at the end to handle any errors. They also combine then/catch with Promise.all for parallel tasks.
Connections
Async/Await
Builds-on
Understanding then and catch is essential because async/await is syntactic sugar over Promises and uses them under the hood.
Error Handling in Synchronous Code
Similar pattern
Catch in Promises is like try/catch in synchronous code, helping learners transfer error handling concepts across asynchronous and synchronous contexts.
Event-driven Programming
Same pattern
Then and catch methods resemble event listeners that respond to future events, connecting asynchronous programming to broader event-driven design.
Common Pitfalls
#1Forgetting to add catch leads to unhandled errors.
Wrong approach:Promise.resolve() .then(() => { throw 'Error'; });
Correct approach:Promise.resolve() .then(() => { throw 'Error'; }) .catch(error => console.log(error));
Root cause:Not understanding that errors in then must be caught explicitly to avoid unhandled rejections.
#2Using then with two arguments instead of catch for errors reduces code clarity.
Wrong approach:Promise.reject('Fail') .then( result => console.log(result), error => console.log('Error:', error) );
Correct approach:Promise.reject('Fail') .catch(error => console.log('Error:', error));
Root cause:Confusing error handling options and not following best practices for readability.
#3Returning a non-Promise value inside then when a Promise is expected causes timing bugs.
Wrong approach:Promise.resolve(5) .then(num => num + 1) .then(result => console.log(result));
Correct approach:Promise.resolve(5) .then(num => Promise.resolve(num + 1)) .then(result => console.log(result));
Root cause:Not realizing that returning a Promise delays the next then, while returning a value runs it immediately.
Key Takeaways
Then and catch methods let you handle success and failure of asynchronous tasks clearly and in order.
Chaining then calls allows sequencing multiple steps, while catch centralizes error handling for the whole chain.
Errors thrown inside then propagate down the chain until caught, preventing silent failures.
Returning Promises inside then delays the next step until the Promise resolves, enabling complex asynchronous flows.
Using catch instead of then's second argument for errors improves code readability and maintainability.