DEV Community

Luca
Luca

Posted on

The two meanings of `finally` in Javascript

As many, if not all, JS developers know, there are two different syntaxes that handle promises, the then/catch/finally:

function runPromiseThen() {
  return fnThatReturnsPromise().then(promiseResult => {
      const result = doSomethingSyncWithResult(promiseResult)
      return result
    }).catch(error => {
      possiblyLogAndHandleErrorSomehow(error)
      return
    }).finally(() => {
      doSomethingLikeNotifyThatThisIsOver()
      return
    })
  }
Enter fullscreen mode Exit fullscreen mode

and the try/await/catch:

async function runPromiseAwait() {
  try {
    const promiseResult = await fnThatReturnsPromise()
    const result = doSomethingSyncWithResult(promiseResult)
    return result
  } catch (error) {
    possiblyLogAndHandleErrorSomehow(error)
    return
  } finally {
    doSomethingLikeNotifyThatThisIsOver()
    return
  }
Enter fullscreen mode Exit fullscreen mode

While they might look like the same, and they mostly behave in the same way, the two functions will return totally different values when called.

In particular, runPromiseThen will return:

  • result when the then path is taken, as no error have been thrown during the execution.
  • null if an error is thrown, since the catch path is taken.

In both cases though, the function doSomethingLikeNotifyThatThisIsOver is called since that's what finally does: it defines a block that is always run no matter what path is taken. Not only that, but the block needs to be run until the end before the promise is resolved. So remember not to put a long sync function in a finally block unless you want to slow down your promise.

And the finally in runPromiseAwait does the same: no matter what path the execution takes, be it the try or the catch, whatever code is written in its blocks is executed.

But there is a catch!
While the finally in a then/catch/finally will not change what the function returns, the try/await/catch will: whatever the finally block returns, is what the whole function will return; no matter what path the execution takes, no matter what fnThatReturnsPromise returns, runPromiseAwait will always return null, since that's what the finally block returns.

That's it.
This is my first post on dev.to, I'm trying to force myself into writing more.

Top comments (0)