Execute Program

JavaScript Concurrency: Promise Cleanup With Finally

Welcome to the Promise Cleanup With Finally lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • In regular JavaScript code, we can use finally to run some code whether an exception occurs or not. This is often used for "cleanup" code that should run regardless of what happens.

  • >
    let cleanedUp = false;
    try {
    // Do nothing.
    } finally {
    cleanedUp = true;
    }
    cleanedUp;
    Result:
    truePass Icon
  • >
    let cleanedUp = false;
    try {
    throw new Error('Something broke!');
    } catch {
    // Silently ignore the error.
    } finally {
    cleanedUp = true;
    }
    cleanedUp;
    Result:
    truePass Icon
  • Promises have a finally as well, but it's a method on the promise object. Like other promise methods, finally returns a new promise.

  • >
    Promise.resolve()
    .finally(() => {
    // Cleanup code goes here.
    });
    Asynchronous Icon Async Result:
  • With then and catch, the callback's return value ends up inside the promise. But the finally callback's return value is ignored. Instead, finally returns a promise that fulfills or rejects with whatever value its parent promise had.

  • If we call finally on a promise that fulfills with 5, then we'll get another promise that fulfills with 5. If we call finally on a rejected promise, we'll get a promise that rejects with the same reason.

  • In short: finally doesn't affect the outcome of the promise. It's there if we want to write code that runs whether the promise fulfills or rejects.

  • >
    let isLoading = true;
    function getUserName() {
    return Promise.resolve()
    .then(() => 'Amir')
    .finally(() => {
    isLoading = false;
    });
    }
    getUserName();
    Asynchronous Icon Async Result:
    {fulfilled: 'Amir'}Pass Icon
  • >
    let isLoading = true;
    function getUserName() {
    return Promise.resolve()
    .then(() => { throw new Error('no such user'); })
    .finally(() => {
    isLoading = false;
    });
    }
    getUserName();
    Asynchronous Icon Async Result:
    {rejected: 'Error: no such user'}Pass Icon