ai js promise then vs catch

By Xah Lee. Date: .

what's the diff of promise .then(yes_f, no_f) vs .catch(on_bad_f)

(ai answer)

.catch(on_bad_f) is just sugar for .then(undefined, on_bad_f). The interesting difference is when you attach both a success and an error handler.

The two forms

p.then(yes_f, no_f)          // two-arg then
p.then(yes_f).catch(on_bad_f) // then + catch

They look similar. They are not the same.

What actually differs

no_f (the second argument of .then) only sees a rejection of p itself.

If yes_f throws, or returns a rejected promise, no_f does not run. That rejection goes to whatever comes after this .then.

.catch sits after yes_f, so it sees:

That’s the whole difference.

Promise.resolve("ok")
  .then(() => {
    throw new Error("boom in success handler");
  }, (err) => {
    console.log("two-arg then:", err.message);  // never runs
  });
// unhandled rejection

Promise.resolve("ok")
  .then(() => {
    throw new Error("boom in success handler");
  })
  .catch((err) => {
    console.log("catch:", err.message);  // "boom in success handler"
  });

Same story if the success handler returns Promise.reject(...) instead of throwing.

When they behave the same

If yes_f never throws and never returns a rejecting promise, both forms treat a rejected p the same way: the error handler runs and the success handler does not.

Extra chaining note

A .catch that handles the error (returns a normal value) recovers the chain. Later .then success callbacks still run. A two-arg .then that “handles” the original rejection does the same for that rejection — but again, it never sees errors from yes_f.

Practical takeaway

Use .then(yes_f).catch(on_bad_f) by default. It catches bugs in the success path too.

Use .then(yes_f, no_f) only when you intentionally do not want errors from yes_f to be handled by no_f (you have another catch later, or you want those to stay unhandled).