Ky’s (Somewhat Poignant) Guide to Asynchronicity and Cryptocurrencies — Part 3
(Also inconsistently referred to as Ky’s Guide to Starting Over 1.8.3 or Ky’s Guide to Powerful Promises in future annotations and subsequent editions)
Making a Promise You Can Keep
Promises are a funny thing when you come to think on them. It’s a statement you make when you want to assure another party that you will (or won’t) do something, based on some condition or circumstance, and even if that event is in the future, you are giving your word that you will eventually do something.
For example, I made a promise to my Norwegian neighbor Nels (the other party) that if he ever brought pickled herring over to my flat (the condition), I would eat some (the something I would do). Now, in truth, I was not expecting him to swing by after returning from a visit back to Oslo with a jar of surslid, but what mattered was that I made a promise that I would do something when a condition was met, and believe me, it was met…
In JavaScript, as of ES6, JavaScript can now make promises too! But more on that in just a moment, patient readers!
This might seem like it has nothing to do with my trials and tribulations in making an app to check the prices of various cryptocurrencies but stick with me. Promises in JavaScript are actually quite useful in the context of making async calls, and I soon found that their power could be leveraged to make my code easier to write and much easier to read.
Dissecting Promises
It came as no surprise to me that those pesky investment bankers came scurrying back to my flat, holding out brochures about investment strategy synergy and mumbling about how the people in their webs “wanted to be there.” I had made a promise to them previously though, about what I would do if they ever came skulking around again, so I grabbed the corn husk broom from my closet and saw them off.
I made promises frequently in my everyday life, but what exactly was a Promise in JavaScript?
A promise in JS is an object that represents an eventual value; they allow us to create powerful abstractions and to provide behavior that is cumbersome to create with event listeners and traditional methods (as we will see in a moment). In effect, a promise gives no guarantee of when an operation will complete, but it does guarantee that when the result of the operation is available the code you provide will be executed, or the error handled as you specify.
It’s quite similar to any of the promises I described earlier; there is a condition that needs to be met, and an action that is executed based on the result. There was no guarantee just when the condition will be determined, but when it is, the action is taken.
This might make more sense when viewed with code, so I’ll walk you through just how I put this all together.
First I looked at how promises in JS are created, as understanding that would help me understand how they are used:
I could see that a promise relies on a condition. Depending on the outcome of some operation the condition would either be successful or unsuccessful. (This might have been receiving a response from an XHR request for example, but in this case, it was checking the value of a randomly generated number). The promise would then set its state to either ‘resolved’ or ‘rejected’, and any code chained to this promise would either enact a success callback or a failure callback based on the promise’s state and the value that was returned in either case (these were the arguments of the `resolve` and `reject` functions).
“But how is that useful?” you ask. Yes, promises might seem a bit ethereal now, but stick with it and the misty outline will take shape!
Contemplating the utility of promises, I considered the previous example with a randomly generated number. I could use two methods to handle the values returned by a resolved or rejected promise:
- `Promise.prototype.then` — invokes a callback using a resolved promise’s return
- `Promise.prototype.catch` — invokes a callback using a rejected promise’s return
“But, really, how is that used?” you press. Let’s give the hazy form before us some more shape…
The pivotal behavior here is that the `then` and `catch` methods return promises themselves, so you can chain one promise to another! This is the magic that allows us to take an elaborate configuration of nested async calls and just chain them from one promise to another!
I tried to bring this out with a more realistic example by referring back to that nasty, nested, pyramid from before. ***link here***
Here is the little Pyramid of Doom that I had constructed before as I made a few subsequent requests to get a coin id, use that id to get its price, then use the price to check the percent growth:
Now, if I altered my `getCoindId` method to return a promise, instead of having to pass in the success and failure callbacks for each method, and having to nest the calls that are depending on the previous async calls all one after the other within `getCoindId` … I could do something like this:
How much easier to read is that?
Now I would just have to handle the error cases. The good news here is that I only had to include one `catch` call at the very end, and if any of the promises in the chain were rejected, the `catch` callback would be invoked with the error passed along!
I could then simplify the calls and add an error catcher to make this code as lean and mean as possible:
Now that nebulous, amorphous cloud that was a JavaScript promise should be a fully formed turkey dinner with all the sides, and you sit with a napkin tucked into your shirt collar, utensils in either hand, ready to make a feast of this once unknowable entity.
Dramatic imagery aside, I had unlocked the power of promises, and I realized that I could now leverage that power to clean up my code. Because I understood the inner workings of requests and responses in JavaScript, I could fix the errors in my CryptoChecker app and get it looking sparkly clean to boot!
Next, I would just need to put all these bits and pieces together into one cohesive bundle. Right after I cleared out the spider traps and heated up a mug of ham juice to take the chill out of the room.
To be continued, or not… We’ll see.
Until next time, or not… We’ll see.
-Ky
Postscript
The story started here. Find out why I started building this app. Also, why you shouldn’t trust investment banking spiders.
The story continued here. Find out how requests can be made with JS and why pyramids are better left to the Egyptians.
The story concludes here. See the CryptoChecker App in all its early 90s terminal style glory.