Promise.prototype.catch()
Exactly then(undefined, onRejected), with one consequence people miss: a handler that merely logs turns a failure into a success, and the rest of the chain carries on with undefined.
Demo
The first case is the behaviour behind most swallowed errors: because the handler returns, the chain is FULFILLED with that value, and everything downstream carries on as though nothing failed. A handler that only logs does exactly the same, returning undefined. The second case rethrows, so the promise stays rejected and the error keeps propagating — which is what a logging handler almost always should do.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| onRejected | Function | yes | Called with the rejection reason. Returning a value fulfils the chain; throwing, or returning a rejected promise, keeps it rejected. |
Return value
Promise — A new Promise. If the handler returns normally the new promise is FULFILLED with that value — the chain recovers. Rethrow to keep it rejected.
Common patterns
p.catch(e => { report(e); throw e; });
const data = await fetchFresh().catch(() => cached);
fetch(u).then(r => r.json()).then(use).catch(handle);
Examples
Pitfalls
await p.catch(e => console.error(e))
await p.catch(e => { console.error(e); throw e; })
p.catch(handle).then(() => { throw new Error("late"); })
p.then(() => { throw new Error("late"); }).catch(handle)
p.catch(() => show("Network error"))
p.catch(e => { if (e instanceof TypeError) throw e; show("Network error"); })
function save() { doSave().catch(log); }
async function save() { await doSave().catch(log); }
When to use
- Recovering with a fallback value, deliberately
- Logging and rethrowing at a boundary
- A final handler at the end of a chain
- Converting a rejection into a result your caller expects
- try/catch reads better in async functions → use that
- You only want cleanup → finally
- The handler only logs → rethrow, or you have silently recovered
- Mid-chain placement → later links escape it
Notes
FAQ
Because the catch handler returned. Returning from a rejection handler is how you RECOVER — it fulfils the chain with that return value. A handler that only logs returns undefined, so the chain succeeds with undefined. Rethrow if you meant to propagate.
p.catch(e => { log(e); throw e; });