Promise chaining means calling multiple .then() methods one after another, where
each step uses the result of the previous step.
It helps run asynchronous tasks in order, avoiding callback hell.
🧠 Why use Promise Chaining?
To perform tasks step-by-step
To avoid nested callbacks
To handle async code cleanly
To pass and transform data between steps
🍔 Real-Life Example: Ordering a Burger
Imagine you order a burger at a restaurant.
Steps happen one after another:
Place order
Chef prepares the patty
Burger is assembled
Order is packed
You receive the burger
Same step-by-step process happens in promise chaining.
<div class="code-terminal-demo">
<style>
.code-terminal-demo {
--win-red: #ff5f57;
--win-yellow: #febc2e;
--win-green: #28c840;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
}
.code-terminal-demo * { box-sizing: border-box; }
.ctd-window {
border-radius: 10px;
overflow: hidden;
box-shadow: 0 8px 30px rgba(0,0,0,0.35);
margin-bottom: 1.5rem;
}
.ctd-titlebar {
background: #2b2b2b;
padding: 0.6rem 0.8rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.ctd-dot { width: 11px; height: 11px; border-radius: 50%; }
.ctd-dot.red { background: var(--win-red); }
.ctd-dot.yellow { background: var(--win-yellow); }
.ctd-dot.green { background: var(--win-green); }
.ctd-filename {
flex: 1;
text-align: center;
color: #9a9a9a;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.75rem;
margin-right: 3.4rem;
}
.ctd-code {
background: #1e1e1e;
color: #d4d4d4;
margin: 0;
padding: 1rem 1.1rem;
font-family: 'IBM Plex Mono', 'Fira Code', monospace;
font-size: 0.78rem;
line-height: 1.65;
overflow-x: auto;
white-space: pre;
}
.tok-kw { color: #569cd6; }
.tok-fn { color: #dcdcaa; }
.tok-str { color: #ce9178; }
.tok-num { color: #b5cea8; }
.tok-com { color: #6a9955; }
.tok-var { color: #9cdcfe; }
.tok-punc { color: #d4d4d4; }
.ctd-run {
display: block;
margin: 0 auto 1.5rem;
border: none;
background: #2563eb;
color: #fff;
padding: 0.55rem 1.3rem;
font-family: 'Inter', system-ui, sans-serif;
font-size: 0.85rem;
font-weight: 600;
border-radius: 6px;
cursor: pointer;
}
.ctd-run:active { transform: scale(0.97); }
.ctd-run:disabled { opacity: 0.5; cursor: default; }
.ctd-term {
background: #0c0c0c;
color: #e5e5e5;
padding: 1rem 1.1rem;
font-family: 'IBM Plex Mono', 'Fira Code', monospace;
font-size: 0.78rem;
line-height: 1.9;
}
.ctd-term .line { display: block; opacity: 0; transition: opacity 0.25s ease; }
.ctd-term .line.is-shown { opacity: 1; }
.ctd-term .prompt { color: #6ee7b7; }
.ctd-term .path { color: #7dd3fc; }
.ctd-term .out { color: #e5e5e5; }
.ctd-term .out.final-line { color: #f4bf75; font-weight: 600; }
.ctd-term .cursor {
display: inline-block;
width: 7px;
height: 1em;
background: #e5e5e5;
vertical-align: text-bottom;
margin-left: 2px;
animation: ctd-blink 1s steps(1) infinite;
}
@keyframes ctd-blink { 50% { opacity: 0; } }
</style>
<div class="ctd-window">
<div class="ctd-titlebar">
<div class="ctd-dot red"></div>
<div class="ctd-dot yellow"></div>
<div class="ctd-dot green"></div>
<div class="ctd-filename">script.js</div>
</div>
<pre class="ctd-code"><span class="tok-kw">function</span> <span class="tok-fn">placeOrder</span><span class="tok-punc">() {</span>
<span class="tok-kw">return</span> <span class="tok-var">Promise</span><span class="tok-punc">.</span><span class="tok-fn">resolve</span><span class="tok-punc">(</span><span class="tok-str">"Order placed"</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-kw">function</span> <span class="tok-fn">preparePatty</span><span class="tok-punc">(</span><span class="tok-var">msg</span><span class="tok-punc">) {</span>
<span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-var">msg</span><span class="tok-punc">);</span>
<span class="tok-kw">return</span> <span class="tok-var">Promise</span><span class="tok-punc">.</span><span class="tok-fn">resolve</span><span class="tok-punc">(</span><span class="tok-str">"Patty prepared"</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-kw">function</span> <span class="tok-fn">assembleBurger</span><span class="tok-punc">(</span><span class="tok-var">msg</span><span class="tok-punc">) {</span>
<span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-var">msg</span><span class="tok-punc">);</span>
<span class="tok-kw">return</span> <span class="tok-var">Promise</span><span class="tok-punc">.</span><span class="tok-fn">resolve</span><span class="tok-punc">(</span><span class="tok-str">"Burger assembled"</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-kw">function</span> <span class="tok-fn">packOrder</span><span class="tok-punc">(</span><span class="tok-var">msg</span><span class="tok-punc">) {</span>
<span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-var">msg</span><span class="tok-punc">);</span>
<span class="tok-kw">return</span> <span class="tok-var">Promise</span><span class="tok-punc">.</span><span class="tok-fn">resolve</span><span class="tok-punc">(</span><span class="tok-str">"Order packed"</span><span class="tok-punc">);</span>
<span class="tok-punc">}</span>
<span class="tok-fn">placeOrder</span><span class="tok-punc">()</span>
<span class="tok-punc">.</span><span class="tok-fn">then</span><span class="tok-punc">(</span><span class="tok-var">preparePatty</span><span class="tok-punc">)</span>
<span class="tok-punc">.</span><span class="tok-fn">then</span><span class="tok-punc">(</span><span class="tok-var">assembleBurger</span><span class="tok-punc">)</span>
<span class="tok-punc">.</span><span class="tok-fn">then</span><span class="tok-punc">(</span><span class="tok-var">packOrder</span><span class="tok-punc">)</span>
<span class="tok-punc">.</span><span class="tok-fn">then</span><span class="tok-punc">((</span><span class="tok-var">res</span><span class="tok-punc">)=></span><span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-var">res</span><span class="tok-punc">))</span>
<span class="tok-punc">.</span><span class="tok-fn">then</span><span class="tok-punc">(() =></span> <span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-str">"Burger delivered!"</span><span class="tok-punc">))</span>
<span class="tok-punc">.</span><span class="tok-fn">catch</span><span class="tok-punc">(() =></span> <span class="tok-var">console</span><span class="tok-punc">.</span><span class="tok-fn">log</span><span class="tok-punc">(</span><span class="tok-str">"Something went wrong!"</span><span class="tok-punc">));</span></pre>
</div>
<button class="ctd-run" id="ctdRun" type="button">▶ Run script.js</button>
<div class="ctd-window">
<div class="ctd-titlebar">
<div class="ctd-dot red"></div>
<div class="ctd-dot yellow"></div>
<div class="ctd-dot green"></div>
<div class="ctd-filename">zsh — node</div>
</div>
<div class="ctd-term" id="ctdTerm">
<span class="line is-shown"><span class="prompt">➜</span> <span class="path">~</span> node script.js</span>
<span class="line out" id="tline1">Order placed</span>
<span class="line out" id="tline2">Patty prepared</span>
<span class="line out" id="tline3">Burger assembled</span>
<span class="line out" id="tline4">Order packed</span>
<span class="line out final-line" id="tline5">Burger delivered!</span>
<span class="line is-shown" id="tlinePrompt"><span class="prompt">➜</span> <span class="path">~</span> <span class="cursor"></span></span>
</div>
</div>
</div>
<script>
(function () {
const scope = document.currentScript.closest('.code-terminal-demo') || document;
const runBtn = scope.querySelector('#ctdRun');
const lineIds = ['tline1', 'tline2', 'tline3', 'tline4', 'tline5'];
const promptLine = scope.querySelector('#tlinePrompt');
runBtn.addEventListener('click', () => {
runBtn.disabled = true;
lineIds.forEach(id => scope.querySelector('#' + id).classList.remove('is-shown'));
promptLine.classList.remove('is-shown');
// The real code has no timers — every .then() resolves instantly.
// Paced here purely so each hand-off in the chain is visible.
const STEP = 500;
lineIds.forEach((id, i) => {
setTimeout(() => scope.querySelector('#' + id).classList.add('is-shown'), (i + 1) * STEP);
});
setTimeout(() => {
promptLine.classList.add('is-shown');
runBtn.disabled = false;
}, (lineIds.length + 1) * STEP);
});
})();
</script>✔ Each step depends on the previous one
✔ Perfect representation of Promise Chaining
🧩 How Promise Chaining Works
Each
.then()returns a new promiseThe returned value is passed to the next
.then()If a
.then()returns a promise, the next waits for itIf any step fails → jumps to
.catch()
❗ Error Handling in a Chain
doTask1()
.then(doTask2)
.then(doTask3)
.catch((err) => console.log("Error:", err));🔁 Returning a Promise Inside .then()
fetchUser()
.then(user => fetchPosts(user.id))
.then(posts => console.log(posts));🌟 finally() in Promise Chains
task()
.then(res => console.log(res))
.catch(err => console.log(err))
.finally(() => console.log("Done!"));🎯 Quick Summary
Promise chaining = running async steps in sequence
Every
.then()creates a new promiseReturned values flow to the next step
Errors go directly to
.catch().finally()runs no matter what