While learning JavaScript and programming in general, I find it useful to create some analogies to understand the concepts better. Here I will share an analogy about Promises in JavaScript. Feel free to contribute in the comments.
In Javascript, if we want to call a function only after an asynchronous function returns, we can use callbacks. Let's say I'm baking a cake with chocolate icing, in that case, my bakeCake()
function is asynchronous and takes prepareIcing()
(that's the callback) as an argument, calling it only when the cake is completely baked.
But in this article we're focusing on using Promises. So how promises can help solve this problem? A promise is an object that wraps an asynchronous action and can be fulfilled with a value if the operation is successful or rejected with a reason, if it fails. This way I'm able to add a handler for a value (or a reason) that I will have only at some point in the future.
Going back to the baking example, I can say my oven is a promise of a cake, because it wraps my baking cake action and starts with a pending state (it's still baking). But I have a smart oven that will tell me when the action finishes. If the baking was successful, it's fulfilled with a cake. Otherwise, it's rejected with a burned cake or any other reason for the failure.
Like we said before, using promises, we can add handlers for its possible states when it settles (it is either fulfilled or rejected). The .then()
method can handle both success and failure (less common), and the .catch()
method only can handle failure.
This is how I would handle a baking simple cake (no icing) action: if it is successful, then I can serve the cake. But if I burn my cake, I can catch the failed cake, throw it in the garbage and order a pie for my dessert instead. 😂
Another thing to keep in mind is that, since one promise returns another promise, they can be chained. In my previous cake with icing example, I can finish baking my cake, then prepare the icing, then with both the cake and the icing ready, cover the cake. In that case, if any of the promises in the chain fails, I can handle all the rejections with only one catch and order a pie.
But there's a better way to do what we did in the last example. My bakeCake()
and my prepareIcing()
functions are independent, which means they can happen at the same time. For that, we can use Promise.all()
to wait for both results (cake and icing) before executing the coverCake()
function.
Inside Promise.all()
, if any of the promises rejects (fails), the entire promise is rejected. Which makes sense, right? I can't cover the cake if either the cake or the icing is missing.
This was a very simplified and summarised explanation of the concept of Promise, and the use of .then()
, .catch()
and Promise.all()
methods. I hope it was clear enough.
Thanks for reading, feel free to contribute in the comments. I promise my next article is already in the oven right now (pending). And eventually, I'll share it on my twitter as soon as it's fulfilled or I'll post pictures of cats if it's rejected.
Bullet points for this article:
- Promises are objects wrapping asynchronous actions.
- Promises start with a pending state, and at some point in the future they settle to a fulfilled (success) or rejected (failure) state.
- A promise returns a new promise that can be used for chaining.
- We can add handlers to the success value or the failure reason once the action returns, by using
.then()
or.catch()
. -
Promise.all()
waits for all the promises to be resolved. If any rejects, it's rejected.
References and recommended further reading
- Illustrated JS: JavaScript asynchronous behaviour
- Asynchronous programing in Eloquent JavaScript by Marijn Haverbeke
- Using promises in MDN Web Docs
Top comments (12)
Ah, yet again a great illustrated article, Marina!
And one can simultaneously start (baking cake & preparing icing) aand order a pie! Then eat the first that's available (Promise.race)!
Warning: don't try to do that at home, you'll end up with both: a cake and a dessert 🙂
btw, Marina , did you know that you can create series of articles in dev.to? press "edit" -> open the "nut" 🔩 menu at the bottom -> add text to series field
Thanks, Kostia! Yes, I thought about including Promise.race() in the example, then I realised it could be confusing. Like you said, in "real life" you'd ended up with both the cake and the pie, right? 🤣 Unless you cancel the delivery or throw away the unfinished cake (not a good idea).
And thanks for letting me know about the series of article, I didn't know that. 😀
Really excellent post :) Thank you.
Thanks, I'm glad you liked it. :D
when I try to bake a cake, it always ends with ordering... so bad at baking cake..
Same here! I don't even bother trying to bake the cake, I go straight to the point and order something. 🥧 😅
Fantastic,explanations were really good!
THANK YOU!
Thanks, happy to read this. :D
This was helpful. Newer to programming and had seen “Promises” when reading, but hadn’t looked into them yet.
Thanks, I'm glad it helped. :D
Greatly visualized ;-)
I'm missing a bit concrete code where the different combinations are shown, nevertheless it's a good start with promises for me ;-)
Great article, Marina! Love the illustrations!