Unlike [Callback Hell](http://stackabuse.com/avoiding-callback-hell-in-node-js/), Promise Hell is accidentally self inflicted. Promise Hell is just a lack a familiarity with Promises. This article will show some Promise Hell scenarios and the steps out get of it. All code snippets are written [ECMAScript 2015](https://github.com/lukehoban/es6features). ### Nested.then(..) with linearly dependent Promises A typical example is Promises that depend on each other. Let’s say we have 3 Promises that depend on each other linearly: `fetchBook()`, `formatBook(book)`, and `sendBookToPrinter(book)`. The naïve code is: ``` fetchBook() .then((book) => { return formatBook(book) .then((book) => { return sendBookToPrinter(book); }); }); ``` The nesting is unnecessary, which simplies the code to: ``` fetchBook() .then((book) > { return formatBook(book); }) .then((book) => { return sendBookToPrinter(book); }); ``` Since these are single liners, the curly braces and return can be omitted. ``` fetchBook() .then((book) => formatBook(book)) .then((book) => sendBookToPrinter(book)); ``` But then we notice we have an identity closure! We can just inline the function: ``` fetchBook() .then(formatBook) .then(sendBookToPrinter); ``` ### Nested .then(..) with independent Promises In another scenario, we might have Promises that can be run independently. Let’s say we have 3 functions that return Promises: `demandMoreDonuts()`, `greet(name)`, and `closeGate()`. The naïve code would be: ``` demandMoreDonuts() .then(() => { return greet('fred') .then(() => { return closeGate(); }); }); ``` How to get out of this situation depends if we care that these Promises are run in serial or in parallel. If we don’t care about the order of the Promises, then this can be simplified to: ``` Promise.all([ demandMoreDonuts(), greet('fred'), closeGate() ]); ``` If we want to serialize the Promise order (say we want to abort early on error), then we can write this as: ``` demandMoreDonuts() .then(() => greet('fred')) .then(closeGate); ``` ### Nested.then(..) with multiple dependent Promises This situation is what most people get hung up on with Promises. In this example, let’s say we have 4 Promises: `connectDatabase()`, `findAllBooks(database)`, `getCurrentUser(database)`, and `pickTopRecommendation(books, user)`. The naïve code is: ``` connectDatabase() .then((database) => { return findAllBooks(database) .then((books) => { return getCurrentUser(database) .then((user) => { return pickTopRecommendation(books, user); }); }); }); ``` Naïvely we will think this is the best we can do. How else can we get a reference to books and user at the same time? This code also has other issues, such as when we call `getCurrentUser(database)`, we have books unnecessarily in scope. The solution is to understand Promises can be held in a reference. We can extract the common bits out. ``` const databasePromise = connectDatabase(); const booksPromise = databasePromise .then(findAllBooks); const userPromise = databasePromise .then(getCurrentUser); Promise.all([ booksPromise, userPromise ]) .then((values) => { const books = values[0]; const user = valuess[1]; return pickTopRecommentations(books, user); }); ``` **But wait**, doesn’t this mean we connect to the database twice? We call `.then(..)` on `databasePromise` twice! *This is a key thing to understand about Promises, they are only ever resolved once per creation.* This means you can call `.then(..)` as many times as you want, and you’ll only ever get one database connection. This is not the case if you call `connectDatabase()` multiple times. The extraction of the values out of promises is a bit ugly. It can be simplifed using the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator), but this is only available in Node.js 5.x or greater. ``` Promise.all([ booksPromise, userPromise ]) .then((values) => pickTopRecommentations(...values)); ``` … or with [destructuring](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment), but this is only available in Node.js 6.x or greater. ``` Promise.all([ booksPromise, userPromise ]) .then(([books, user]) => pickTopRecommentations(books, user)); ``` Alternatively it can be simplified with [Ramda](http://ramdajs.com)’s [apply](http://ramdajs.com/0.19.0/docs/#apply). ``` Promise.all([ booksPromise, userPromise ]) .then(R.apply(pickTopRecommentations)); ``` Much more complex examples can be formed using a combination of these scenarios. I hope this will help somebody escape Promise Hell. If you have more specific examples that I have not covered, feel free to [tweet me](https://twitter.com/pyrolistical). This article was originally posted on [Medium](https://medium.com/@pyrolistical/how-to-get-out-of-promise-hell-8c20e0ab0513#.mthxn9iwr) and I am the original author ([proof](https://twitter.com/pyrolistical/status/758133796755546112)). @cheetah I have my eye on you.
author | pyrolistical |
---|---|
permlink | how-to-escape-promise-hell |
category | javascript |
json_metadata | {"tags":["javascript","programming","promises"],"users":["cheetah"],"links":["http://stackabuse.com/avoiding-callback-hell-in-node-js/"]} |
created | 2016-07-27 02:55:03 |
last_update | 2016-07-27 03:10:48 |
depth | 0 |
children | 7 |
last_payout | 2016-08-26 15:02:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.022 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 5,179 |
author_reputation | 665,138,270 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 392,823 |
net_rshares | 42,705,092,933 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
noisy | 0 | 30,515,498,751 | 100% | ||
johnerfx | 0 | 9,560,849,678 | 100% | ||
johnerminer | 0 | 1,015,832,036 | 100% | ||
superfreek | 0 | 1,251,550,421 | 100% | ||
luisucv34 | 0 | 136,243,303 | 100% | ||
cire81 | 0 | 4,996,854 | 100% | ||
relationships | 0 | 44,759,527 | 100% | ||
shanejonas | 0 | 64,525,626 | 100% | ||
pyrolistical | 0 | 63,428,133 | 100% | ||
oldas | 0 | 47,408,604 | 100% | ||
peterjhendrick | 0 | 0 | 100% |
Hi! I am a content-detection robot. This post is to help manual curators; I have NOT flagged you. Here is similar content: https://medium.com/@pyrolistical/how-to-get-out-of-promise-hell-8c20e0ab0513 NOTE: I cannot tell if you are the author, so ensure you have proper verification in your post (or in a reply to me), for humans to check!
author | cheetah |
---|---|
permlink | re-how-to-escape-promise-hell-20160727t025548 |
category | javascript |
json_metadata | "" |
created | 2016-07-27 02:56:03 |
last_update | 2016-07-27 02:56:03 |
depth | 1 |
children | 3 |
last_payout | 2016-08-26 15:02:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 338 |
author_reputation | 942,693,160,055,713 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 392,834 |
net_rshares | 2,100,927,662 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
cheetah | 0 | 1,993,069,807 | 15% | ||
cheetah27 | 0 | 107,857,855 | 100% |
proof is at end of post
author | pyrolistical |
---|---|
permlink | re-cheetah-re-how-to-escape-promise-hell-20160727t025548-20160727t030523985z |
category | javascript |
json_metadata | {"tags":["javascript"]} |
created | 2016-07-27 03:05:24 |
last_update | 2016-07-27 03:05:24 |
depth | 2 |
children | 2 |
last_payout | 2016-08-26 15:02:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 23 |
author_reputation | 665,138,270 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 392,976 |
net_rshares | 0 |
!cheetah whitelist
author | anyx |
---|---|
permlink | re-pyrolistical-re-cheetah-re-how-to-escape-promise-hell-20160727t025548-20160727t030705311z |
category | javascript |
json_metadata | {"tags":["javascript"]} |
created | 2016-07-27 03:07:06 |
last_update | 2016-07-27 03:07:06 |
depth | 3 |
children | 1 |
last_payout | 2016-08-26 15:02:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 18 |
author_reputation | 98,676,136,100,181 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 393,005 |
net_rshares | 0 |
how do you make greater than show up properly in markdown reformatted code? the site is auto converting to > to > I did a bad thing. I used mimic and replaced > with >
author | pyrolistical |
---|---|
permlink | re-pyrolistical-how-to-escape-promise-hell-20160727t030627638z |
category | javascript |
json_metadata | {"tags":["javascript"]} |
created | 2016-07-27 03:06:27 |
last_update | 2016-07-27 03:22:24 |
depth | 1 |
children | 0 |
last_payout | 2016-08-26 15:02:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 183 |
author_reputation | 665,138,270 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 392,993 |
net_rshares | 0 |
Congratulations @pyrolistical! You have received a personal award! [](http://steemitboard.com/@pyrolistical) 2 Years on Steemit <sub>_Click on the badge to view your Board of Honor._</sub> > Do you like [SteemitBoard's project](https://steemit.com/@steemitboard)? Then **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
author | steemitboard |
---|---|
permlink | steemitboard-notify-pyrolistical-20180725t220847000z |
category | javascript |
json_metadata | {"image":["https://steemitboard.com/img/notify.png"]} |
created | 2018-07-25 22:08:45 |
last_update | 2018-07-25 22:08:45 |
depth | 1 |
children | 0 |
last_payout | 2018-08-01 22:08:45 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 501 |
author_reputation | 38,975,615,169,260 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 65,975,264 |
net_rshares | 0 |
Congratulations @pyrolistical! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@pyrolistical/birthday3.png</td><td>Happy Birthday! - You are on the Steem blockchain for 3 years!</td></tr></table> <sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@pyrolistical) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=pyrolistical)_</sub> ###### [Vote for @Steemitboard as a witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1) to get one more award and increased upvotes!
author | steemitboard |
---|---|
permlink | steemitboard-notify-pyrolistical-20190725t205230000z |
category | javascript |
json_metadata | {"image":["https://steemitboard.com/img/notify.png"]} |
created | 2019-07-25 20:52:30 |
last_update | 2019-07-25 20:52:30 |
depth | 1 |
children | 0 |
last_payout | 2019-08-01 20:52:30 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 636 |
author_reputation | 38,975,615,169,260 |
root_title | "How to escape Promise Hell" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 88,742,635 |
net_rshares | 0 |