Trystan Sarrade
Trystan Sarrade

Reputation: 744

Why Promise.catch() also call .then() if it is not in the right order?

I wanted to know why the promise below both call the catch() and then() method.

function testpromise(){
  return new Promise((resolve, reject)=>{
    reject("Error");
  })
}


testpromise()
.catch((err)=>{console.log(err)})
.then(()=>{console.log("Then")})

But why this one doesn't ? (I only moved the .then() method before the .catch() one).

function testpromise(){
  return new Promise((resolve, reject)=>{
    reject("Error");
  })
}


testpromise()
.then(()=>{console.log("Then")})
.catch((err)=>{console.log(err)})

Is this a bug ? It's kind weird that I can't get the catch() method before the .then(). For me putting catch before then allow me to quickly check if I handle possible errors correctly. I have dozens of promises wrote like so and I just noticed that it will also call my .then() method right away, which is not good.

Upvotes: 7

Views: 7883

Answers (3)

charlietfl
charlietfl

Reputation: 171689

A catch returns a promise so unless you throw or return another rejected promise it will resolve to the next then() in the chain

Following contrived example should help you visualize it

testpromise()
  .catch((err) => {
    console.log('First catch=', err)
    return 'Catch message'; // implicit return value, with no return next then receives undefined
  })
  .then((fromCatch) => {
    console.log("from first catch =", fromCatch)
  })
  .then(testpromise) // return another rejected promise to next catch
  .then(() => console.log('Not called'))
  .catch((err) => {
    console.log('Second catch');
    throw 'New Error'
  })
  .then(() => console.log('Not called #2'))
  .then(() => console.log('Not called #3'))
  .catch(err => console.log('Final catch =', err))

function testpromise() {
  return new Promise((resolve, reject) => {
    reject("Error");
  })
}

Upvotes: 9

Jared Smith
Jared Smith

Reputation: 21965

Consider the following code:

try {
  throw new Error("catch me if you can!");
} catch (err) {
  // whatever
}

console.log("hi");

Because that is the synchronous equivalent of this:

Promise.reject(new Error("catch me if you can!"))
  .catch(_ => { /* whatever */ })
  .then(_ => console.log("hi"));

Each time you add a .then or .catch it returns a new promise, it doesn't modify the old one in place. So it's not that the order is wrong, it's that it matters. Otherwise you couldn't do something like this:

fetch(someURL)
  .then(response => response.json())
  .then(doSomethingWithJSON)
  .catch(err => {
     handleRequestFailure(err);
     console.error(err);
     return err;
  })
  .then(result => {
    if (result instanceof Error) {
      return fallbackRequest();
    }
  })
  .catch(handleFallbackError);

Upvotes: 3

Akam
Akam

Reputation: 141

A .catch() is really just a .then() without a slot for a callback function for the case when the promise is resolved.

MDN Promises Documentation

Think of the .then() function as a chain, each one does something according to the resolved value, and passes the returned value to the next .then() in the chain, or if an error thrown, to the .catch() method.

Upvotes: 2

Related Questions