Deep Tech Point
first stop in your tech adventure
Finally in JavaScript – error handling is not only about try and catch anymore, it’s about a Promise and finally() method, too
December 28, 2021 | Javascript

This article is going to take you into the world of the “finally”. We will take a look at how to handle the try/catch/finally blocks, but we will also learn more about the Promise and a finally() method.

1. What you should know about the try/catch/finally blocks?

We’ve already taken a peek at one of the most recognized exception handling mechanisms – the try/catch/finally statement, but let’s summarize the main points again:

When we are using the blocks, we must understand the follow-up of the return values. Let’s take a look at one example of the try/catch/finally blocks in the function, where we expect a user to insert a number that is higher than 3, but lower than 6.
We’ve prepared several scenarios with if conditionals:

When you’re using the try/catch/finally blocks, you should be aware of which block’s return values will be returned.
Let’s take a look at the code, where the finally statement will help you execute the code after the try and catch, no matter what the result is:





Please insert a number between 3 and 6:

1. What you should know about the Promise and a finally() method

First, let's recap what a Promise in Javascript is. A Promise is an object used as a proxy for a value that is not known at the moment. Maybe this is the very reason, it is called a Promise - the value is not yet known, but JavaScript PROMISES to return that value at some point. So, for example a synchronous method (such as try/catch/finally statement is) would immediatelly return the final value, but a Promise allows you to use an asynchronous method. That means that you would wait for the final value to be returned, and afterwards you would do the next things you planned to do when that final value is returned. This is done is the form of .then() methods, which is a common practice to learn if you're working with Promises. .then() is sort of attaching a callback functions onto Promise so it can handle what comes back from it - .then() takes a callback function and returns another Promise.
Some of the built-in Promise-specific methods are .catch() and .finally(). Here, we are going to focus on finally() method, which was introduced in ES2018 and represents a method that is always executed regardless a promise was fulfilled or rejected, so basically when the promise is settled. With a finally() method you can add a code that cleans the resource when the promise is settled, which enables you to bypass duplicate code in the then() and catch() methods.

It the example below we're duplicating the code in the then() and catch() methods:

promise
    .then(result => {
        // system processes the result
        // system cleans the resources
    })
    .catch(error => {
        // system handles the error
        // system cleans the resources
    });

But as said above the finally() method helps you avoid duplicating the code because you can put the entire code that cleans the resources in the finally method. Therefore, the finally() method can be useful if you want to do some processing or cleanup once the promise is settled, whatever the outcome is - either the promise is resolved or rejected.

promise
    .then(result => {
        // system processes the result
    })
    .catch(error => {
        // system handles the error
    })
    .finally(() => {
        // system cleans the resources
    });

In terms of avoiding duplicate code and cleaning it, we can try to compare the finally() method to the finally block that is covered in the try/catch/finally statement that we've covered above. The finally() method is used in asynchronous code, while the finally block from the try/catch/finally statement is used in the synchronous code to clean up the resources.

So, what happens in the above code? The Promise executes immediately - it either resolves to a single value, or rejects with an error object. So, when the system rejects the Promise, the return value passes through .then()s and then the .catch() picks it up. But, once a promise has been settled - either rejected or resolved - it cannot be settled again. The job can be either: finished with success and results in a value, which means the job is resolved, or another option is, rejection, which means an error has occurred and that error is the error object.

As the MDN says: "Promise.prototype.finally() - The finally() method returns a Promise. When the promise is settled, i.e either fulfilled or rejected, the specified callback function is executed. This provides a way for code to be run whether the promise was fulfilled successfully or rejected once the Promise has been dealt with. This helps to avoid duplicating code in both the promise's then() and catch() handlers."


function checkPassword(password) {
  return new Promise((resolve, reject) => {
    if (password === "secret") {
      resolve("Password is correct.");
    } else {
      reject(new Error("Password is not correct"));
    }
  });
}

checkPassword("secret")
  .then((msg) => {
    console.log(msg);
  })
  .catch((err) => {
    console.error(err);
  })
  .finally(() => {
    console.log("You completed a test");
  });

We've created a function called checkPassword(), which does what it says - it checks whether your password is correct. We defined the password with if conditional to be strictly equal to "secret". Within this function, we want to have a return of a new Promise - either the Promise is resolved or rejected - either your password is correct or not. If your password is correct (password === secret) we have a resolution of a Promise with a message "Password is correct", and if your password isn't correct, we get an error, or in Promise's terminology, we have a rejection that console logs "Password is not correct". Through a function call (with a help of .then), a Promise results in console.log(msg) or catches (.catch) an error and messages "Password is not correct". Nevertheless, at the very end, either the Promise is rejected or resolved, we get a definite .finally(), which results in a console.log "You completed a test".

It is also important to bring out that the finally() method is very similar to calling .then(onFinally, onFinally) however there are a few differences: