Back to KB
Difficulty
Intermediate
Read Time
7 min

Promises: Then's Second Argument

By Codcompass Team··7 min read

Divergent Promise Paths: Leveraging Isolated Rejection Handlers for Robust Flow Control

Current Situation Analysis

Modern JavaScript development has largely standardized on async/await for asynchronous control flow. While this syntax improves readability, it has inadvertently caused a decline in fluency with native Promise chain mechanics. A critical area of degradation is the misunderstanding of the .then() method's dual-argument signature: then(onFulfilled, onRejected).

Many developers treat .then(handlerA, handlerB) as a mere shorthand for .then(handlerA).catch(handlerB). This assumption is technically incorrect and leads to subtle control flow bugs. The core pain point is the inability to distinguish between error recovery and path divergence.

  • Error Recovery: You attempt an operation. If it fails, you handle the error. If the operation succeeds but the handler fails, you also want to handle that error.
  • Path Divergence: You have a primary operation. If it succeeds, execute path A. If it fails, execute path B. Crucially, if path A fails, you do not want path B to trigger. Path B is a fallback for the source, not a recovery for path A.

This distinction is often overlooked because the ECMAScript specification defines the behavior of missing arguments in .then(). If onFulfilled is omitted or not a function, it is replaced by an identity function (value) => value. If onRejected is omitted or not a function, it is replaced by a "thrower" function (reason) => { throw reason; }. This mechanism ensures that values and errors propagate through the chain, but it also means that providing both arguments creates two mutually exclusive execution slots attached to the same promise settlement.

Misusing .catch() when you need isolation results in "catch-all" behavior where fallback logic inadvertently triggers due to errors in the success handler, masking bugs and creating unpredictable state transitions.

WOW Moment: Key Findings

The isolation provided by the two-argument .then() creates a structural difference in how errors propagate compared to chained .catch() calls. The following comparison highlights the behavioral divergence based on where errors originate.

PatternError ScopeHandler IsolationExecution ModelBest Use Case
.then(success, fallback)Source Promise OnlyHighDivergentFallback logic; mutually exclusive paths.
.then(success).catch(fallback)Source + successLowSequential RecoveryError recovery; handling failures from any upstream step.
.catch(fallback).then(success)Source OnlyMediumPre-processingTransforming errors into values before processing.

Why this matters: The .then(success, fallback) pattern allows you to architect flows where a fallback mechanism is strictly bound to the upstream promise. If success throws an error, fallback is never invoked. This prevents scenarios where a fallback (e.g., loading default configuration) attempts to run because the primary handler (e.g., applying configuration) crashed, which could lead to redundant operations or inconsi

🎉 Mid-Year Sale — Unlock Full Article

Base plan from just $4.99/mo or $49/yr

Sign in to read the full article and unlock all 635+ tutorials.

Sign In / Register — Start Free Trial

7-day free trial · Cancel anytime · 30-day money-back