Never Make A (JavaScript) Promise You Can’t Keep

It’s only been a week and a half into beginning the JavaScript section of the Flatiron School’s web development program and I am more overwhelmed than I thought was possible. The first week of it was all about giving us as much material as is possible that can fit into the schedule and I have been trying to recover since. What makes it worse is comparing myself to others who seem to get it and thinking that I too should be “getting it.” But the issue with this mindset is that by constantly focusing on what other people are seemingly understanding, I am not focusing on my own journey and targeting my own problem areas.

It’s helped me to also realize that I should not expect to be a master at JavaScript after really only learning it for just a matter of days. Writing the actual code and breaking things down into small, digestible pieces is also very helpful and doesn’t make it all seem as bad as when trying to look out at what looks like a mountain. The journey becomes much easier when you think about just one step at a time. With that being said, let’s dive into the topic I chose to write about…

JavaScript Promises

While combing through the incredibly diverse and abundant amount of JavaScript topics, promises seemed to catch my attention and for good reason: they give our code the appearance of asynchronous behavior even though at its core JavaScript is a synchronous, blocking, single-threaded language. Essentially what this means is that all code is executed in sequence, not in parallel.

Under the hood of the JavaScript engine however, I/O (input/output) operations can fetch data over the internet with AJAX or over WebSocket connections, or query data from a database such as MongoDB. All of these operations are done in parallel to the execution of your code, thus giving what seems to be async behavior.

Basic fetch request to an API endpoint.

A promise is an object that represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. If the promise is successful, then it determines what happens next after the event or operation. An event can be a timer finishing or data coming back from an AJAX call. It’s as if we are asking the server for some data in the background and the promise “promises” to give us the data at a certain time in the future.

Promise Properties

A Promise can be in one of these states:

  • fulfilled — The action relating to the promise succeeded
  • rejected — The action relating to the promise failed
  • pending — Hasn’t fulfilled or rejected yet
  • settled — Has fulfilled or rejected

A pending promise can either be fulfilled with a value, or rejected with a reason (error). When either of these options happens, the associated handlers queued up by a promise’s then method are called.

As the Promise.then() and Promise.catch() methods return promises, they can be chained:

A promise has its own methods, which you call to tell the promise what will happen when it is successful or when it fails. The methods a promise provides are “then(…)” for when a successful result is available and “catch(…)” for when something went wrong.

Every .then() should either return a new promise or just a value or object which will be passed to the next .then() in the chain. Another important thing to notice is that even though we are doing two different asynchronous requests we only have one .catch() where we handle our errors. That’s because any error that occurs in the promise chain will stop further execution and an error will end up in the next .catch() in the chain.

The code that is executed when the request has finished, referring to the subsequent .then() calls, is put on the event loop just like a callback function would be. This means you cannot access any variables passed to or declared in the promise chain outside the promise. The same goes for errors thrown in the promise chain. You must also have at least one .catch() at the end of your promise chain for you to be able to handle errors that occur. If you do not have a .catch(), any errors will silently pass and fade away and you will have no idea why your promise does not behave as expected.

Without .catch(), an error in the success handler will go uncaught.

Promise chain with an error handler:

With .catch(), both error sources are handled.

Final Thoughts

When first exposed to promises/promise chains/AJAX fetches, I felt lost and bewildered. I could not understand what I was looking at or what exactly was going on in the code. But what helped was looking at many, many examples of application projects that required fetching data from an API and then using that data to do something else. Through the several iterations, it all started to become clearer what was going on and how the promises were working/doing their job.

This pattern of not understanding, and then finally having that “aha” moment doesn’t happen right away and can take either a few hours to a few days depending on the complexity of the concept. It’s become a routine in my life as a student learning the ins and outs of a programming language and is something that I have come to embrace instead of fearing. There is a behemoth of information and knowledge out there to learn, but if I don’t have the right mindset going into the learning, then I will already be at a disadvantage from the get go. It is my goal to attack every knowledge gap that I have with as much effort and enthusiasm as possible! Thank you for reading and I hope you enjoyed this blog. Till next time!