Feels allows users to track how they are feeling. With a simple form, users can rate how they are feeling from 1–100 and then add different emotions to their entry. User can then view their past entries and see how their mood has changed over time and to remembers the good and bad moments they’ve had in the past.
One of the core UI elements of Feels is the use of modals:
Modals are a great way to hide content until the user performs an action which then triggers a separate window to open up on top of the main page. Here, I use a modal to open up a panel that allows users to add/remove emotions from their entry. Users can easily interact and scroll in this panel without interacting with the main page and then once they are done, click the x in the top right or click outside the panel to close the modal.
If you want to check out Feels yourself, feel free to download/clone the project from GitHub.
What is a Promise?
Simply put, a
Here are some great things about
Promises that will help show how and why they are used:
#1 — Promises guarantee the execution of asynchronous operations
Sometimes with asynchronous functions, we want to wait until the functions have executed before calling other function. For example, we may want to request all of our Blogs from our backend API before rendering blogs on the page.
fetchBlogs() // Asynchronous function
renderBlogs() // Synchronous function
This is what our code may look like if we wrote this in a synchronous way. We called
fetchBlogs(), which is an asynchronous function. That means as our application is performing that operation, we call
renderBlogs() before confirming that we finished fetching our blogs. This should raise some serious alarms in your head!
What if we try to render all our blogs before we finish fetching them? Well, there would be no blogs to render! Here’s a possible fix, using the power of promises:
then() magically fix our problem? Well,
then() is an instance method we can call on a
Promise (remember that all asynchronous functions return a Promise). It ensures us as programmers that the operations wrapped up in the
then() will always be executed before. That means,
fetchBlogs() will always finish executing before
renderBlogs() is called.
#2 — Promises allow us to chain asynchronous operations
then() method also allows us to create something called a promise chain, which is a sequence of asynchronous operations that will execute one after the other, like synchronous functions. That’s because
then() returns — you guessed it — another
Here’s an example:
So what’s happening here? First off, assume that all of these functions are asynchronous functions. Now, because we know that
then() returns a
Promise we can keep chaining calls to
then() providing a different callback operation each time. By creating a promise chain, we ensure that our operations will be performed in order.
#3 — Promises can handle both success and failure
then() also allows us to provide a second callback function that will be called if the previous
Promise has a rejected state.
Here we can use
then() to handle both fulfilled and rejected
Promises. However, more often than not, we will see the following used instead:
catch() is very similar to
then() except it’s callback function will only be used in the case of a rejected
then(undefined, callbackRejection) when
catch() is used.
How I used Promises to manage fetch requests
The following are a series of snippets of code that is used to fetch entries from a database, fetch the emotions associated with each entry from a database, and then render that data onto the page:
fetch() is an asynchronous function and thus returns a
The start of the
loadEntries() function is a standard fetch request but I want to highlight how
createEntries() in line 69 uses promises.
Moving into the
entry.js file, we see that it returns the result of
Promise.all(...). This method wraps up an array of promises into a single
Promise that guarantees the execution of each of the promises in the list before any other functions that are chained on.
I do this here because in order to create a new Entry object, I need to perform another fetch request, wait for that request to be fulfilled and then use that result to create the Entry.
Following the promise chain, we see that on line 54 in
entry.js we call
Emotion.getEmotions() which returns another
Promise that ensures we fetch all the Emotion data we need from our backend (lines 44–48 in
emotion.js). Once that
Promise is fulfilled, then we execute lines 55–57 in
entry.js. That is where we finally create our new Entry object.
Because I wrapped all of these operations in promises, I can ensure that everything is happening in the order that I want. Thus, only after I’ve fetched all of the Entry data, fetched all of the Emotion data, created new Emotion objects, created new Entry objects, will I then execute line 70–72 in
index.js, which is where I render the entries.
Thanks for reading!
If you’ve made it all the way here, you can check out more about promises in the official documentation on Using Promises.
I hope this was helpful and showed you how to implement promises into your own projects!