Telerik blogs

In today’s posts we will look at the concept of promises in JavaScript and how we can get started using them in our workflows today.

Promises With a Breakfast Story

One great way to understand promises is to use it in a common scenario you are already used to. Let us assume you have a flatmate, Alex, and you cook together to manage resources. So for breakfast today, you wanted to make noodles but there is no garlic powder at home and you both love garlic in your noodles. The second breakfast option is toast if you cannot find garlic powder.

You both are very hungry and it’s your turn to make breakfast, but you need Alex’s help so you ask him to go to the supermarket nearby to get garlic powder. You inform him that you will not wait for him to get back to start making breakfast, so it is important that he promises to call you from the supermarket. This is so that you can switch to making toast if there is no garlic powder or start boiling noodles if there is, so that food is almost ready when he arrives.

A Promise

A JavaScript promise is an object that shows the eventual fulfillment or failure of a task that does not necessarily need to be completed as soon as it is set up. It is a kind of proxy for a value that is not known yet for an asynchronous operation when a promise is made. This basically creates an avenue for async methods to work like they are normal synchronous methods—the only difference is, instead of returning a value, the async will return a promise to provide the value overtime.

The promise syntax looks like this:

const myPromise = new Promise(function(myResolve, myReject) {
// "Producing Code" (May take some time)

  myResolve(); // when successful
  myReject();  // when error
});

// "Consuming Code" (Must wait for a fulfilled Promise)
myPromise.then(
  function(value) { /* code if successful */ },
  function(error) { /* code if some error */ }
);

States of JavaScript Promises

A promise is usually in one of three states. One is when the promise has just been created and the async operation has not taken place—this is called pending. Think of it as when Alex goes out of the house before he gets to the supermarket and checks for garlic powder.

The second state of a promise is the fulfilled state. Recall the async operation is to get garlic powder and so if Alex finds garlic powder, then he informs me and noodles become the sure breakfast—that is a successful operation. Here, myResolve would be called and the associated handler queued using the then method executes.

The other option is the rejected state, where Alex did not find garlic powder. He informs me and I switch to making toast for breakfast. That is a failed operation. Here, myReject would be called and the associated handler queued using the then method executes.

Why Would You Want To Use Promises?

One of the reasons promises were built was to avoid callback hell. So callbacks can be used to do the work that promises do—however, they can get super complex as the project grows and the logic gets chained. Meanwhile, the way promises are structured, it is way easier to work with async operations as you use it like you would any synchronous function (promises are async written in functions the way synchronous functions are written).

Also, you can use promises for async operations whose outcome you do not know yet and still decide beforehand what happens for every possible outcome value.

Creating a Promise

For our scenario described above, here is a corresponding promise definition:

const myPromise = new Promise((resolve, reject) =>{
    let getGarlic = true
    console.log('pending...');
    if (getGarlic == true) {
        resolve('Resolved: There is Garlic Powder')
    } else {
        reject('Rejected: There is no Garlic Powder')    
    }
})

If you save this code block in a new js file and run it, you will see that it is in the pending stage. JavaScript provides the then methods for promises to execute callbacks based on a rejection or a resolution.

Adding Callbacks

Let us add callbacks for both in the code block we already have:

const myPromise = new Promise((resolve, reject) =>{
    let getGarlic = true
    console.log('pending...');
    if (getGarlic == true) {
        resolve('resolved: There is Garlic Powder')
    } else {
        reject('rejected: There is no Garlic Powder')    
    }
})
myPromise.then((message) => {
    console.log('Make noodles because the promise is' + ''+ message)
}).catch((message) =>{
    console.log('Make toast because the promise is ' + ''+ message) 
})

Now we just used the then and catch methods to solve for both a success case and a failure case. You see how with the current state of the getGarlic the right scenario kicks in and I am accurately informed of what to do before Alex comes home.

You see that if the promise is successful, the then method is executed, and if it fails the catch method is executed. You also see the resolve and reject arguments were injected to the callbacks by default and we could log it in the console.

Conclusion

In this post you got a good introduction to promises in JavaScript with code blocks to illustrate. This is such a wonderful tool, especially if you are pulling data from third-party sources or doing other operations that might take a while to complete and you do not want every other process to wait. This also ensures if the desired outcome is not achieved you can solve for that by retrying or doing something completely different. Happy hacking!


5E9A474B-EBDB-439E-8A4A-3B041B0BEDA6
About the Author

Nwose Lotanna Victor

Nwose Lotanna Victor is a web technology enthusiast who documents his learning process with technical articles and tutorials. He is a freelance frontend web developer based in Lagos, Nigeria. Passionate about inclusion, community-building and movies in Africa, he enjoys learning new things and traveling.

Related Posts

Comments

Comments are disabled in preview mode.