5 min read

A night out at the theater

Banner image

A real life-ish example to help explain how Javascript promises work and why they're necessary.


Javascript Help
Published

If you’re a beginner at Javascript or you frequently help out beginners in online communities you know that the #1 thing that beginner programmers have problems with is Promises, or the concept of async programming in Javascript. Despite being a very useful construct in computer science, it’s not a very intuitive concept for most people learning programming for the first time.

If you’ve been linked here by me or someone else, please take the time to read this as Promise is a word you’re going to be running into for as long as you’re writing Javascript code and it will haunt you the longer you keep running away from it.

Why Do Promises Exist?

The most important thing about Promises you have to understand that promises are plans for the future, they’re not events that have been completed yet.

To better visualize what this might mean, imagine you’re running the part of the human brain responsible for making decisions. You have 3 functions you want to complete tonight called watchMovie, goHome and goToSleep. These are functions that you want to call in the order you’re thinking of. You don’t want to sleep before you watch the movie and you definitely don’t want to get behind the wheel while you’re sleeping either.

Intuitively, the way most people would approach this problem would be something straightforward like:

watchMovie()
goHome()
goToSleep()

However, these 3 are events that will take you 3 to 4 hours to complete and you, as the decision making part of the brain, have other human things to do like breathing, talking, thinking and any other activity you can think of. If you have to wait for the movie to finish before you can do any of these things again, you’re in for a lot of trouble.

In order to solve this issue you’ve decided that these functions shouldn’t completely prevent you from doing what you need to do. You should just be able to tell a part of your brain to focus on watching the movie. This way you can do things like get your nose to breathe while you’re watching the movie so you don’t die and get your mouth to tell your friend sitting next to you to stop talking so hE CAN SHUT UP WHY IS HE TALKING DURING A MOVIE THIS ISN’T A CAFETERIA JUST LET ME WATCH THE THING IN PEACE!

This also means that when you call these special functions, you’re actually just sending them off to different parts of your brain to be done later and moving on ASAP since you have other things to be scheduling. Because of that, running the earlier code:

watchMovie()
goHome()
goToSleep()

Now means that you’re getting a part of your brain to watch a movie, get in your car to drive home and also sleep at the same time. Not what we were trying to do at all.

Sequencing Different Actions Together

When you’re asking different parts of your brain to do these, you get a receipt or quite literally, a Promise, back saying that the thing you wanted to happen will be done. You will also be notified when it’s completed so you can do other actions afterwards.

This is exactly the function of .then() in Javascript. It lets you run a function only after a “future” action like watching a movie has finished. With that in mind, we can now chain watching a movie and going home like ES6

watchMovie().then(() => {
  goHome()
})

What if watchMovie() returned some ideas about the movie and you wanted to go to sleep, dreaming about those? It might be tempting to do something like:

let dreams = null
watchMovie().then(movieThoughts => {
  dreams = movieThoughts
  goHome()
})
goToSleep(dreams)

But .then() only runs when the movie has finished running and like we established above, you have to move on with the things you do so in this scenario you’re going to tell a part of your brain to watch a movie and then immediately tell another part of your brain to go to sleep with null dreams since you didn’t wait for the movie to finish

Instead the correct way to do it would be

watchMovie().then(movieThoughts => {
  goHome().then(() => {
    goToSleep(movieThoughts)
  })
})

With this you’re waiting for the previous scheduled promise to finish before running the next ones.

This isn’t going to be a full tutorial on Promises, if you’re looking for more resources you can check out these resources.

https://ui.dev/async-javascript-from-callbacks-to-promises-to-async-await/

https://javascript.info/promise-basics

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

And my personal favorite:

Reason for Promises in Real Javascript

The reason why Javascript behaves this way by default and why a language like Python or Java doesn’t is because even though Node is a big player in server side technology these days, Javascript was historically meant to only be run in a browser. And in a browser, Javascript is tasked with re-rendering the HTML on your screen and scheduling other things about web pages. If every time you make a request, Javascript has to wait 1+ second for the request to finish, much like how your brain wouldn’t be able to breathe, Javascript won’t be able to paint changes to the screen like animations, button clicks, typing and so on, leading to terrible user experience.

Promises are a confusing concept so if you’re still confused, don’t worry too much about it. This idea is going to click as you keep working with it more and more.