This Gist was automatically created by Carbide, a free online programming environment.
Last active
December 18, 2025 00:56
-
-
Save sliminality/fcc5cb01a1cd24551f26a9110d802b63 to your computer and use it in GitHub Desktop.
nested promises example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ///Problems with nested Promises: very easy to **forget to return**, thus breaking the Promise chain\\- No arrow functions yet, must explicitly return each time//- People are accustomed to line starting with **doC(…)** from CPS. Nesting Promises is **structurally similar** to CPS, but error handling only works at the top level! | |
| doA() | |
| .then(function (a) { | |
| doB() ///_⚠ Missing __**return**_ | |
| .then(function (b) { | |
| doE() | |
| doC(a, b) ///_⚠ Missing __**return**_ | |
| }) | |
| }) | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Got an error:" + err) }) ///⚠ Won't catch any errors from **doB**, **doE**, **doC** | |
| function doA() { return Promise.resolve("a") } | |
| function doB() { return Promise.resolve("b") } | |
| function doC(a, b) { return Promise.resolve(`${a}${b}`) } | |
| // function doD(c) { return c === "ab" ? Promise.resolve("d") : Promise.reject(new Error("Wrong input: expected ab, got " + c)) } | |
| function doE() { return Promise.resolve() } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ///Problem: suppose you want to structure some async code like this.\\\\` // ┌──────▶ D// │// │ b c//A ─────▶ B ─────▶ C ─────▶ …//│ ▲//└─────────────────┘// a`\\\\Using continuation-passing style ("callback hell") and pre-ES2015 syntax for authenticity, it would look something like this:\\\\\\\\\\ | |
| doA(function (err, a) { | |
| // if (err) { return handleError(err) } | |
| doB(function (err, b) { | |
| // if (err) { return handleError(err) } | |
| doE(function (err) { | |
| // if (err) { return handleError(err) } | |
| }) | |
| doC(a, b, function (err, c) { | |
| // if (err) { return handleError(err) } | |
| doD(c, function (err, d) { | |
| window.alert("Success: " + d) | |
| }) | |
| }) | |
| }) | |
| }) | |
| function handleError(err) { | |
| window.alert("Caught error:", err) | |
| } | |
| function doA(next) { next(null, "a") } | |
| function doB(next) { next(null, "b") } | |
| function doC(a, b, next) { next(null, a + b) } | |
| function doE(next) { next(null) } | |
| function doD(c, next) { | |
| if (c === "ab") { | |
| next(null, "d") | |
| } else { | |
| next(new Error("Wrong input: expected ab, got " + c), null) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ///How do we write this code using early-style Promises? | |
| function doA() { return Promise.resolve("a") } | |
| function doB() { return Promise.resolve("b") } | |
| function doC(a, b) { return Promise.resolve(`${a}${b}`) } | |
| // function doD(c) { return c === "ab" ? Promise.resolve("d") : Promise.reject(new Error("Wrong input: expected ab, got " + c)) } | |
| function doE() { return Promise.resolve() } | |
| doA() | |
| .then(function (a) { | |
| return Promise.all([a, doB()]) ///Need to use **Promise.all** and return a pair to thread **a** into the next call | |
| }) | |
| .then(function (ab) { | |
| doE() | |
| return doC(ab[0], ab[1]) ///Now unpack the tuple **a**, **b** to pass arguments to **doC** | |
| }) | |
| // .then(doD) | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Got an error:" + err) }) | |
| doA() ///This is a far cry from the fluent syntax in the advertisement for Promises! (need to thread parameters, etc.)\\\\So, let's try rewriting this with **nested Promises**: | |
| .then(function (a) { | |
| return doB() | |
| .then(function (b) { | |
| doE() | |
| return doC(a, b) ///Can shadow **a** and **b** directly without threading | |
| }) | |
| }) | |
| // .then(doD) | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Got an error:" + err) }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ///Even if you **return** correctly, there are pitfalls | |
| doA() | |
| .then(function (a) { | |
| return doB() ///_✔ Correctly returned_ | |
| .then(function (b) { | |
| doE() ///_(Don't return, just send off this call)_ | |
| return doC(a, b) ///_✔ Correctly returned_ | |
| }) | |
| }) | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Got an error:" + err) }) ///_✔ \_Now, this \_will_ catch errors from **doA**, **doB**, **doC** | |
| function doA() { return Promise.resolve("a") } | |
| function doB() { return Promise.resolve("b") } | |
| function doC(a, b) { return Promise.resolve(`${a}${b}`) } | |
| // function doD(c) { return c === "ab" ? Promise.resolve("d") : Promise.reject(new Error("Wrong input: expected ab, got " + c)) } | |
| function doE() { throw new Error("E failed") } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ///Can try adding inner .**catch** clause… | |
| doA() | |
| .then(function (a) { | |
| return doB() | |
| .then(function (b) { | |
| // doE() //.catch(function (err) { window.alert("Inner error:" + err) }) ///\_✔ \_Catches **doE** if **doE** rejects a Promise, but _not_ if **doE** throws exception | |
| return doC(a, b) | |
| }) | |
| }) | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Outer error:" + err) }) ///\_✔ \_Catches **doA**, **doB**, **doC** (exception or rejected Promise), \\Catches **doE **if thrown exception, _not_ if rejected Promise | |
| function doA() { return Promise.resolve("a") } | |
| function doB() { return Promise.resolve("b") } | |
| // function doC(a, b) { return Promise.resolve(`${a}${b}`) } | |
| // function doC(a, b) { return Promise.reject(new Error("c")) } | |
| function doC(a, b) { throw new Error("c") } | |
| function doE() { return Promise.reject(new Error("E failed")) } | |
| // function doE() { throw new Error("E failed") } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| doA() ///Where to add **catch** for **doC(…)**? | |
| .then(function (a) { | |
| return doB() | |
| .then(function (b) { | |
| doE() | |
| return doC(a, b) // ?? ///Here? | |
| }) // ?? ///Here? | |
| }) // ?? ///Here? | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Outer error:" + err) }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ///Promises were _kind of_ like synchronous exception handling, but not quite.\\- Exceptions would coalesce through subsequent chained calls, but not up and down the call stack//- Wanted you to be able to use Promises, sync code interchangeably, so allowed **.then(x => 1)** and would Promisify **1**, but this meant it wasn't clear when exceptions were thrown/caught. | |
| doA() | |
| .then(function (a) { | |
| return doB() | |
| .then(function (b) { | |
| doE() | |
| return doC(a, b) | |
| }) | |
| }) | |
| .then(function (d) { window.alert("Success: " + d) }) | |
| .catch(function (err) { window.alert("Got an error:" + err) }) | |
| function doA() { return Promise.resolve("a") } | |
| function doB() { return Promise.resolve("b") } | |
| function doC(a, b) { return Promise.resolve(`${a}${b}`) } | |
| // function doD(c) { return c === "ab" ? Promise.resolve("d") : Promise.reject(new Error("Wrong input: expected ab, got " + c)) } | |
| function doE() { throw new Error("E: Hi") } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment