Most developers first meet Continuation-Passing Style without realizing it. If you have ever written a callback in JavaScript, you have already used it. 𝗪𝗵𝗮𝘁 𝗶𝘀 𝗖𝗼𝗻𝘁𝗶𝗻𝘂𝗮𝘁𝗶𝗼𝗻-𝗣𝗮𝘀𝘀𝗶𝗻𝗴 𝗦𝘁𝘆𝗹𝗲? Continuation-Passing Style (CPS) is a pattern where a function does not return a result directly. Instead, it receives another function, called a continuation, and passes the result to it. Instead of saying: "Here is the result" we say: "When you are ready, call this function with the result" 𝗛𝗼𝘄 𝘄𝗲 𝗻𝗼𝗿𝗺𝗮𝗹𝗹𝘆 𝘄𝗿𝗶𝘁𝗲 𝗶𝘁: function add(a, b) { return a + b; } function multiply(a, b) { return a * b; } const sum = add(2, 3); const result = multiply(sum, 4); console.log(result); 𝗖𝗣𝗦 𝘃𝗲𝗿𝘀𝗶𝗼𝗻: function add(a, b, continuation) { continuation(a + b); } function multiply(a, b, continuation) { continuation(a * b); } add(2, 3, (sum) => { multiply(sum, 4, (product) => { console.log(product); }); }); The functions no longer return values. They pass control forward. 𝗪𝗵𝘆 𝗶𝘀 𝘁𝗵𝗶𝘀 𝗽𝗼𝘄𝗲𝗿𝗳𝘂𝗹? Because execution flow becomes explicit. Instead of relying on the call stack and returns, we decide what happens next. This makes CPS especially useful for: • Asynchronous operations • Non-blocking execution • Error handling • Custom control flow • Building interpreters and compilers Before Promises and async/await, JavaScript relied heavily on this model. 𝗪𝗵𝗮𝘁 𝗮𝗯𝗼𝘂𝘁 𝗰𝗮𝗹𝗹𝗯𝗮𝗰𝗸 𝗵𝗲𝗹𝗹? CPS gives powerful control over execution flow. But without proper composition it can lead to deeply nested callbacks, often called "callback hell". That was not a flaw of the idea itself. It was a signal that we needed better abstractions. Promises and async/await did not replace CPS. They abstracted it. Every then is a continuation. Every await compiles down to continuation logic under the hood. Understanding CPS helps you: • Understand how async actually works • Reason about execution order • Appreciate modern abstractions • Think more clearly about control flow The next time you write async/await, remember: there is a continuation hiding underneath. #JavaScript #FunctionalProgramming #ComputerScience #SoftwareEngineering
You learned CPS the moment you wrote your first callback — you just didn’t know its fancy name, async/await didn’t kill it, it just put a nice suit on callback logiс 😁
A great reminder that async/await is just a convenient syntactic layer. Essentially, every await is really a continuation, just hidden behind syntactic sugar. Understanding CPS greatly enhances your thinking about control flow — especially when you start to understand how event loops and microtasks work
The reframe at the end is the key insight - async/await didn't replace CPS, it just made it readable. Most developers treat Promises as magic and never think about what's underneath, which is fine until something breaks in an unexpected order and you have no mental model to debug with. The "callback hell was a signal, not a flaw" point is worth sitting with. The idea itself was sound - explicit control flow is genuinely powerful. The problem was that we were writing it by hand without abstractions, which doesn't scale. Same pattern shows up everywhere in engineering: the raw concept is solid, the tooling just needs to catch up.