Published on

Mastering finally clause in JavaScript, for beginners

Authors

What is finally clause in JavaScript?

The finally clause in JavaScript is used together with try and catch statements to provide a block of code that will always be executed, regardless of whether an exception was thrown or caught.

The code in the finally block is guaranteed to run after the code in the try block and any associated catch block(s). This makes it useful for performing cleanup tasks, such as closing a file or database connection, or for releasing resources that were acquired in the try block.

An example of using the finally clause:

try {
  // code that may throw an exception
} catch (error) {
  // code to handle the exception
} finally {
  // code that will always be executed
}

When to use finally clause in JavaScript

The finally clause in JavaScript is useful for performing cleanup tasks or releasing resources that were acquired in the try block.

Here are a few examples of how to use the finally clause in your JavaScript code:

Closing a file or database connection

If you open a file or database connection in the try block, you can use the finally block to ensure that the connection is closed, even if an exception is thrown.

Releasing resources

If you acquire a resource, such as a lock or semaphore, in the try block, you can use the finally block to release the resource, regardless of whether an exception is thrown.

Logging

You can use finally block to log an event, such as a function call, whether it completes successfully or not.

Cleaning up after an asynchronous operation

You can use a try-catch-finally block to handle errors thrown by asynchronous operations.

Handling return statements

Even if a return statement is called inside the try or catch block, the code inside the finally block will still be executed before the function exits, this allows you to perform some action before the function exits.

Demo time

Let’s see finally clause in conjunction to try-catch block in action. We’ll cover few cases step-by-step. Let’s go.

Case 1: try block execute without any error(exception)

// List of assets and operations to perform on some financial assets
const getOperationByAssetType = {
  bank: () => `Bank accounts needs to be updated.`,
  stocks: () => `Stocks generate good returns in long-term.`,
}

// Module.js
function performOperationInDatabase() {
  try {
    console.log('Connect to database...')
    console.log('Perform action:')
    console.log(`\t${getOperationByAssetType['bank']()}`)
    console.log(`\t${getOperationByAssetType['stocks']()}`)
    console.log('Save data...')
  } catch (e) {
    console.error('Something went wrong.')
  } finally {
    console.log('Close database connection...')
  }
}

// Server.js
console.log('Starting server...')

performOperationInDatabase()

We get the following output by executing the code above: code output of case 1 where try block execute without any error(exception)

Case 2: An error is thrown in try block and code in catch block executes

As soon as we try to perform operation on crypto asset type our code throw an error because crypto is a bad investment. In fact it is not an investment 😛

The error thrown in try block is caught in catch block but still finally clause gets executed at the end.

The code will look as below after making the described changes:

// List of assets and operations to perform on some financial assets
const getOperationByAssetType = {
  bank: () => `Bank accounts needs to be updated.`,
  stocks: () => `Stocks generate good returns in long-term.`,
}

// Module.js
function performOperationInDatabase() {
  try {
    console.log('Connect to database...')
    console.log('Perform action:')
    console.log(`\t${getOperationByAssetType['bank']()}`)
    console.log(`\t${getOperationByAssetType['stocks']()}`)
    // NOTE: 'crypto' does not exist in object therefore executing undefined will throw an error
    console.log(`\t${getOperationByAssetType['crypto']()}`)
    console.log('Save data...')
  } catch (e) {
    console.error('Something went wrong.')
  } finally {
    console.log('Close database connection...')
  }
}

// Server.js
console.log('Starting server...')

performOperationInDatabase()

We get the following output by executing the code above:

code output for case 2

Case 3: What happen when we use return statement inside try block?

Let’s remove the faulty line from our code and use a return statement in our try block.

We want to test whether the code in finally clause gets executed or not. In other words, does using a return statement affects the execution of finally clause.

The code will look as below after making the described changes:

// List of assets and operations to perform on some financial assets
const getOperationByAssetType = {
  bank: () => `Bank accounts needs to be updated.`,
  stocks: () => `Stocks generate good returns in long-term.`,
}

// Module.js
function performOperationInDatabase() {
  try {
    console.log('Connect to database...')
    console.log('Perform action:')
    console.log(`\t${getOperationByAssetType['bank']()}`)
    console.log(`\t${getOperationByAssetType['stocks']()}`)
    console.log('Save data...')

    return 'TRANSACTION_ID'
  } catch (e) {
    console.error('Something went wrong.')
  } finally {
    console.log('Close database connection...')
  }
}

// Server.js
console.log('Starting server...')

const result = performOperationInDatabase()
console.log(`Result: ${result}`)

We get the following output by executing the code above:

code output for case 3

Surprise, surprise!! finally clause is still being executed before returning the result.

Case 4: What happen when we also use a return statement inside finally clause?

Let’s add a return statement in our finally clause as well.

The code will look as below after making the described changes:

// List of assets and operations to perform on some financial assets
const getOperationByAssetType = {
  bank: () => `Bank accounts needs to be updated.`,
  stocks: () => `Stocks generate good returns in long-term.`,
}

// Module.js
function performOperationInDatabase() {
  try {
    console.log('Connect to database...')
    console.log('Perform action:')
    console.log(`\t${getOperationByAssetType['bank']()}`)
    console.log(`\t${getOperationByAssetType['stocks']()}`)
    console.log('Save data...')

    return 'TRANSACTION_ID'
  } catch (e) {
    console.error('Something went wrong.')
  } finally {
    console.log('Close database connection...')
    return 'SAY_NO_TO_CRYPTO'
  }
}

// Server.js
console.log('Starting server...')

const result = performOperationInDatabase()
console.log(`Result: ${result}`)

You might be thinking, wait a minute, this can’t be right. 🤔 Well, the code runs without an error and we get the following output by executing the code above:

code output for case 4

It turns out that the return statement in the finally block kind of overrides the return value from try or catch clause.

I do not have a concrete scenario where you might need to do that but it does not hurt to know. So there it is.

Conclusion

The finally clause in JavaScript is useful for performing cleanup tasks or releasing resources that were acquired in the try block. Use it to your advantage :)