In JavaScript, Promises are used to handle asynchronous operations. It is just a placeholder for a pending task that is yet to be completed.

Promises have three states:

  1. 'pending' - ย Where the task is still being executed.
  2. 'fulfilled' - The task has been successfully executed and a value is returned.
  3. 'rejected' - ย Task has failed to execute and returned an error message if available.

In modern JavaScript, you can implement and access the value of a promise using:

  1. Promise.then()
  2. Async - Await

Promise.then()

In this method, in order to access the value of a promise, we simply call a "then()" method followed by the promise.

const promise = Promise.resolve("This is a fulfilled promise");

promise
  .then((value) => {
    console.log(value); //This is a fulfilled promise  ๐Ÿ‘ˆ
  })
  .catch((err) => {
    console.log(err); 
  });

In the above code, we created a promise using "Promise.resolve()" method and saved it to a variable. We can then call a "then()" method on this variable, which will contain the returned promise value as a parameter to the function. We can use this value to do further calculations.

If you noticed, we used a "catch()" method followed by the "then()" method in the example code. This is to handle a promise rejection. The following code will result in rejected promise. We can create a promise rejection using "Promise.reject()" method.

const promiseRejected = Promise.reject("This is a rejected promise");

promise
  .then((value) => {
    console.log(value);
  })
  .catch((err) => {
    console.log(err); //This is a rejected promise  ๐Ÿ‘ˆ
  });

Async-await

This is the second method you can use to handle a JavaScript Promise return value. Async-await method is generally used inside a javascript function. ย The following examples will show how to handle the fulfilment or rejection of a promise.

const promise = Promise.resolve("This is a promise");

async function PromiseExample() {
  try {
    const value = await promise;
    console.log(value); //This is a promise  ๐Ÿ‘ˆ
  } catch (error) {
    console.log(error);
  }
}

PromiseExample();

We created a sample promise using the "Promise.resolve()" method and saved it to a variable. Then, we called the variable along with an "await" operator inside an asynchronous function.

Important - A function inside which an "await" operator is called should always be declared with an "async" keyword in order to make the function capable of asynchronous execution.

Now, we will create a promise rejection using "Promise.reject()" method to see how a rejection is handled.

const promiseRejected = Promise.reject("This is a rejected promise");

async function PromiseExample() {
  try {
    const value = await promise;
    console.log(value);
  } catch (error) {
    console.log(error); //This is a rejected promise  ๐Ÿ‘ˆ
  }
}

PromiseExample();

Notice how rejections are handled using a "try-catch" block. This is the technique to retrieve the reason for a promise rejection.

Using a try-catch block is necessary when using "Async-await" method to handle the rejection. If we get an unhandled error from a promise due to not having a "catch" method, we will never know what have caused the error.

Using Async-await outside a function

There might be situations where you need to use "async-await" outside the javascript function. This is possible with certain tweaks. However, it was not supported in the earlier version of NodeJS and browsers. Only NodeJS versions after "16.12.0" and modern browsers support this.

An "await" outside a function is called a top-level "await". In order to enable top-level await, we need to include the JavaScript file as a "module" inside the "HTML" file.

<script type="module" src="index.js"></script>

Now we can write our "await" operator outside a function like this :

const promise = Promise.resolve("This is a promise");

try {
  const value = await promise;
  console.log(value); //This is a promise  ๐Ÿ‘ˆ
} catch (error) {
  console.log(error); 
}
Using a try-catch block is extremaly important when calling a top-level 'await', since it can disrupt the running program and crash the server. There, it is best practice to use try-catch at every scenario when in doubt.

Thank you for reading the article. Check out my featured posts to find other interesting articles.