JavaScript Promise.prototype.finally() Method

The JavaScript Promise.prototype.finally() method, introduced in ES9 (ECMAScript 2018), allows you to execute a callback once a promise is settled, regardless of whether it was fulfilled or rejected. This method is particularly useful for cleanup operations or actions that need to be performed after an asynchronous task completes. In this comprehensive guide, we will explore everything you need to know about the finally() method, including what it is, why it is useful, where and how to use it, and when it is most beneficial.

What is the JavaScript Promise.prototype.finally() Method?

The finally() method is a method on the Promise prototype that registers a callback to be executed once the promise is settled (either fulfilled or rejected). The callback function passed to finally() does not receive any arguments and has no impact on the value of the promise. This method is ideal for tasks that should be performed regardless of the outcome of the promise.

Syntax

The syntax for the finally() method is:

JavaScript
promise.finally(onFinally);
  • onFinally: A function to be executed when the promise is settled.

Example

JavaScript
let myPromise = new Promise((resolve, reject) => {
  // Simulate an asynchronous operation
  setTimeout(() => {
    resolve("Success! ๐ŸŽ‰");
  }, 1000);
});

myPromise
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("Cleanup operations completed. ๐Ÿงน");
  });

// Output after 1 second:
// Success! ๐ŸŽ‰
// Cleanup operations completed. ๐Ÿงน

In this example, the finally() method is used to execute cleanup operations after the promise is fulfilled.

Why Use the JavaScript Promise.prototype.finally() Method?

The finally() method offers several benefits:

  1. Simplifies Cleanup: Provides a convenient way to perform cleanup operations regardless of the promise’s outcome.
  2. Improves Code Readability: Makes code more readable by separating the cleanup logic from the main promise handling logic.
  3. Consistency: Ensures that certain actions are always performed after an asynchronous task completes.

Simplifies Cleanup Example

Without finally():

JavaScript
let myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Success! ๐ŸŽ‰");
  }, 1000);
});

myPromise
  .then((message) => {
    console.log(message);
    // Cleanup operations
    console.log("Cleanup operations completed. ๐Ÿงน");
  })
  .catch((error) => {
    console.log(error);
    // Cleanup operations
    console.log("Cleanup operations completed. ๐Ÿงน");
  });

With finally():

JavaScript
let myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Success! ๐ŸŽ‰");
  }, 1000);
});

myPromise
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("Cleanup operations completed. ๐Ÿงน");
  });

Where to Use the JavaScript Promise.prototype.finally() Method?

The finally() method can be used in various scenarios to ensure that certain actions are always performed after a promise is settled:

  1. Closing Resources: Close files, database connections, or network connections.
  2. Resetting States: Reset UI elements, form fields, or global variables.
  3. Logging: Log completion of asynchronous tasks.

Closing Resources Example

JavaScript
let openDatabaseConnection = () => {
  return new Promise((resolve) => {
    console.log("Database connection opened.");
    setTimeout(() => {
      resolve();
    }, 1000);
  });
};

let closeDatabaseConnection = () => {
  console.log("Database connection closed.");
};

openDatabaseConnection()
  .then(() => {
    console.log("Performing database operations...");
  })
  .finally(() => {
    closeDatabaseConnection();
  });

// Output:
// Database connection opened.
// Performing database operations...
// Database connection closed.

Resetting States Example

HTML
<button id="loadDataButton">Load Data</button>
<script>
  document.getElementById('loadDataButton').addEventListener('click', () => {
    let loadData = () => {
      return new Promise((resolve, reject) => {
        console.log("Loading data...");
        setTimeout(() => {
          resolve("Data loaded successfully! ๐Ÿ“ฆ");
        }, 2000);
      });
    };

    loadData()
      .then((message) => {
        console.log(message);
      })
      .finally(() => {
        document.getElementById('loadDataButton').disabled = false;
        console.log("Button reset. ๐Ÿ”„");
      });

    document.getElementById('loadDataButton').disabled = true;
  });
</script>

// Output after button click:
// Loading data...
// Data loaded successfully! ๐Ÿ“ฆ
// Button reset. ๐Ÿ”„

Logging Example

JavaScript
let fetchData = () => {
  return new Promise((resolve, reject) => {
    console.log("Fetching data...");
    setTimeout(() => {
      resolve("Data fetched successfully! ๐Ÿ“Š");
    }, 1000);
  });
};

fetchData()
  .then((message) => {
    console.log(message);
  })
  .finally(() => {
    console.log("Fetch operation completed. ๐Ÿ“");
  });

// Output:
// Fetching data...
// Data fetched successfully! ๐Ÿ“Š
// Fetch operation completed. ๐Ÿ“

How to Use the JavaScript Promise.prototype.finally() Method?

Basic Usage

To use finally(), simply attach it to a promise chain.

JavaScript
let myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Success! ๐ŸŽ‰");
  }, 1000);
});

myPromise
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("Cleanup operations completed. ๐Ÿงน");
  });

Using finally() with async/await

You can use the finally() method in conjunction with async/await.

JavaScript
let fetchData = () => {
  return new Promise((resolve, reject) => {
    console.log("Fetching data...");
    setTimeout(() => {
      resolve("Data fetched successfully! ๐Ÿ“Š");
    }, 1000);
  });
};

(async () => {
  try {
    let data = await fetchData();
    console.log(data);
  } catch (error) {
    console.log(error);
  } finally {
    console.log("Fetch operation completed. ๐Ÿ“");
  }
})();

When to Use the JavaScript Promise.prototype.finally() Method?

When Ensuring Cleanup

Use finally() to ensure that cleanup operations are always performed after an asynchronous task, regardless of its outcome.

JavaScript
let performTask = () => {
  return new Promise((resolve, reject) => {
    console.log("Performing task...");
    setTimeout(() => {
      resolve("Task completed successfully! โœ…");
    }, 1000);
  });
};

performTask()
  .then((message) => {
    console.log(message);
  })
  .finally(() => {
    console.log("Cleanup operations completed. ๐Ÿงน");
  });

When Resetting UI Elements

Use finally() to reset UI elements after an asynchronous operation.

JavaScript
<button id="submitButton">Submit</button>
<script>
  document.getElementById('submitButton').addEventListener('click', () => {
    let submitForm = () => {
      return new Promise((resolve) => {
        console.log("Submitting form...");
        setTimeout(() => {
          resolve("Form submitted successfully! ๐Ÿ“");
        }, 2000);
      });
    };

    submitForm()
      .then((message) => {
        console.log(message);
      })
      .finally(() => {
        document.getElementById('submitButton').disabled = false;
        console.log("Button reset. ๐Ÿ”„");
      });

    document.getElementById('submitButton').disabled = true;
  });
</script>

// Output after button click:
// Submitting form...
// Form submitted successfully! ๐Ÿ“
// Button reset. ๐Ÿ”„

When Logging Completion

Use finally() to log the completion of an asynchronous operation.

JavaScript
let downloadFile = () => {
  return new Promise((resolve) => {
    console.log("Downloading file...");
    setTimeout(() => {
      resolve("File downloaded successfully! ๐Ÿ“ฅ");
    }, 1000);
  });
};

downloadFile()
  .then((message) => {
    console.log(message);
  })
  .finally(() => {
    console.log("Download operation completed. ๐Ÿ“");
  });

// Output:
// Downloading file...
// File downloaded successfully! ๐Ÿ“ฅ
// Download operation completed. ๐Ÿ“

Advanced Examples

Chaining finally() with Multiple Promises

You can chain finally() with multiple promises to handle cleanup operations after each stage.

JavaScript
let stepOne = () => {
  return new Promise((resolve) => {
    console

.log("Step one...");
    setTimeout(() => {
      resolve("Step one completed! โœ…");
    }, 1000);
  });
};

let stepTwo = () => {
  return new Promise((resolve) => {
    console.log("Step two...");
    setTimeout(() => {
      resolve("Step two completed! โœ…");
    }, 1000);
  });
};

stepOne()
  .then((message) => {
    console.log(message);
    return stepTwo();
  })
  .then((message) => {
    console.log(message);
  })
  .finally(() => {
    console.log("All steps completed. ๐Ÿ");
  });

// Output:
// Step one...
// Step one completed! โœ…
// Step two...
// Step two completed! โœ…
// All steps completed. ๐Ÿ

Using finally() in Real-world Applications

In real-world applications, you might use finally() to reset states, close connections, or perform other cleanup tasks.

JavaScript
let fetchData = () => {
  return new Promise((resolve, reject) => {
    console.log("Fetching data...");
    setTimeout(() => {
      reject("Error fetching data. โŒ");
    }, 1000);
  });
};

fetchData()
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    // Reset UI elements
    console.log("Resetting UI elements. ๐Ÿ”„");
    // Close database connection
    console.log("Closing database connection. ๐Ÿ”");
    // Log completion
    console.log("Fetch operation completed. ๐Ÿ“");
  });

// Output:
// Fetching data...
// Error fetching data. โŒ
// Resetting UI elements. ๐Ÿ”„
// Closing database connection. ๐Ÿ”
// Fetch operation completed. ๐Ÿ“

Summary

The JavaScript Promise.prototype.finally() method is a powerful tool for ensuring that cleanup operations are performed after a promise is settled, regardless of whether it was fulfilled or rejected. By understanding and using finally() effectively, you can write cleaner, more maintainable code. Practice using finally() in different scenarios to see its full potential and improve your asynchronous programming skills.

Leave a Reply