Before we get started, let’s review some fundamentals necessary to understand Promises and Asynchronous behavior.
Functions are first-class data. This means a function can be an argument to another function and a function can be the return value of another function. This concept allows for the use of callback functions. A callback function, simply, is when a function is passed into another function as an argument yet invoked at a later moment.
It is also important to know the specific way in which JavaScript runs its code. Under the hood, JavaScript has an “Execution Stack.” The Execution Stack has many execution contexts. Your code (i.e functions) is executed in the Global Execution Context within the Execution Stack. When a function is done being executed, that function’s execution context is removed from the stack. JavaScript runs each individual execution context because JavaScript runs each line of code one at a time. This is called “synchronous” behavior.
This is where “asynchronous” behavior in JavaScript comes into importance. AJAX calls, like “fetch”, allow for multiple things to happen as the code executes. If you remember a callback function, JavaScript recognizes it, starts to run the code, but does not execute the code until it is invoked. Therefore, asynchronous implements the ability for more complex functionality as JavaScript is not stuck to rendering one line of code at a time.
Fetch introduces an important concept called “Promises.” A Promise is simply an object from the Promise class and it further encapsulates asynchronous behavior in JavaScript. Promises take the idea of callbacks and “dries” the code, as callback functions can be lengthy and repetitive.
Here is how Promises work gathered into a simple analogy I read online. You are hungry. You are trying to decide what to eat for dinner. You know you will eat dinner but you do not know what yet --- this is the Promise; the idea that you will eat but do not know the specific meal. You go out to get tacos. If you go to your favorite taco restaurant and they have not yet sold out of tacos, you will buy the tacos and eat them for dinner at home -- this would be a Promise fulfilled AND an invoked, successful callback. Yet, if your favorite restaurant is sold out of tacos, this would be the Promise rejected. You would then go back home and eat a grilled cheese -- making this the invoked failure callback.
This analogy helps to visualize the concept of Promises. A new Promise is pending and its result value is undefined. A fulfilled Promise is resolved and results in a value and a successful callback. Meanwhile, a rejected (or failed) Promise results in an error which is usually a failure callback. These three Promise statuses: fulfilled, pending and rejected determine the behavior and the result.
The statuses also work alongside Promise’s built-in instance methods: then(), catch() and finally(). If the Promise status is pending, then is fulfilled, then()is executed. If the Promise status is pending then is rejected, catch() is executed. The then() method takes a callback function that executes whenever the promise resolves (or is fulfilled). Likewise, the catch() method takes a callback that executes whenever the promise is rejected. This callback takes an error parameter to catch the error information.
While a Promise mirrors the intense abstraction that JavaScript is known for, a Promise introduces the abstraction as a way to merely help your code execute in the most efficient manner. It is definitely hard to grasp and see its total effect on your code, at first, but it is very worthwhile to learn about. I have definitely benefited from doing the extra research and coming to my own conclusions about Promises and asynchronous behavior in JavaScript.
Top comments (0)